From 97e7dd8b20c075df9fa396f9b026628542bfa105 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Tue, 2 Feb 2010 02:06:44 +0000 Subject: [PATCH] fix krb5-1.7.1 final tag git-svn-id: svn://anonsvn.mit.edu/krb5/tags/krb5-1-7-1-final@23687 dc483132-0cff-0310-8789-dd5450dbe970 --- krb5-1-7/README | 1210 ++ krb5-1-7/doc/Makefile | 158 + krb5-1-7/doc/admin.texinfo | 5414 ++++++ krb5-1-7/doc/api/Makefile | 40 + krb5-1-7/doc/api/ccache.tex | 239 + krb5-1-7/doc/api/errors.tex | 310 + krb5-1-7/doc/api/fancyheadings.sty | 233 + krb5-1-7/doc/api/fixunder.sty | 48 + krb5-1-7/doc/api/free.tex | 266 + krb5-1-7/doc/api/functions.sty | 70 + krb5-1-7/doc/api/intro.tex | 299 + krb5-1-7/doc/api/keytab.tex | 221 + krb5-1-7/doc/api/krb5.ist | 26 + krb5-1-7/doc/api/krb5.tex | 1827 ++ krb5-1-7/doc/api/krb5idx.sty | 10 + krb5-1-7/doc/api/libdes.tex | 38 + krb5-1-7/doc/api/libos.tex | 486 + krb5-1-7/doc/api/library.tex | 114 + krb5-1-7/doc/api/rcache.tex | 207 + krb5-1-7/doc/api/tables.tex | 79 + krb5-1-7/doc/bug-report.texinfo | 10 + krb5-1-7/doc/build.texinfo | 1052 ++ krb5-1-7/doc/ccapi/Doxyfile | 281 + krb5-1-7/doc/ccapi/ccache-api-v2.html | 1217 ++ krb5-1-7/doc/ccapi/html/doxygen.css | 310 + krb5-1-7/doc/ccapi/html/doxygen.png | Bin 0 -> 1281 bytes ...roup__cc__ccache__iterator__reference.html | 96 + .../html/group__cc__ccache__reference.html | 96 + .../html/group__cc__context__reference.html | 161 + ..._cc__credentials__iterator__reference.html | 133 + .../group__cc__credentials__reference.html | 197 + .../html/group__cc__string__reference.html | 96 + .../group__ccapi__constants__reference.html | 407 + .../html/group__ccapi__types__reference.html | 138 + .../doc/ccapi/html/group__helper__macros.html | 1377 ++ krb5-1-7/doc/ccapi/html/index.html | 85 + .../doc/ccapi/html/structcc__ccache__d.html | 43 + .../doc/ccapi/html/structcc__ccache__f.html | 722 + .../html/structcc__ccache__iterator__d.html | 43 + .../html/structcc__ccache__iterator__f.html | 117 + .../doc/ccapi/html/structcc__context__d.html | 43 + .../doc/ccapi/html/structcc__context__f.html | 513 + .../ccapi/html/structcc__credentials__d.html | 67 + .../ccapi/html/structcc__credentials__f.html | 85 + .../structcc__credentials__iterator__d.html | 43 + .../structcc__credentials__iterator__f.html | 85 + .../html/structcc__credentials__union.html | 118 + .../html/structcc__credentials__v4__t.html | 358 + .../html/structcc__credentials__v5__t.html | 334 + krb5-1-7/doc/ccapi/html/structcc__data.html | 94 + .../doc/ccapi/html/structcc__string__d.html | 67 + .../doc/ccapi/html/structcc__string__f.html | 51 + krb5-1-7/doc/coding-style | 566 + krb5-1-7/doc/contributing.txt | 70 + krb5-1-7/doc/copyright.texinfo | 721 + krb5-1-7/doc/definitions.texinfo | 174 + krb5-1-7/doc/dnssrv.texinfo | 93 + krb5-1-7/doc/dnstxt.texinfo | 38 + krb5-1-7/doc/document-list.texinfo | 24 + krb5-1-7/doc/glossary.texinfo | 64 + krb5-1-7/doc/implement/Makefile | 38 + krb5-1-7/doc/implement/ccache-i.tex | 224 + krb5-1-7/doc/implement/cksum-i.tex | 31 + krb5-1-7/doc/implement/crc-32-i.tex | 20 + krb5-1-7/doc/implement/encrypt-i.tex | 164 + krb5-1-7/doc/implement/fancyheadings.sty | 233 + krb5-1-7/doc/implement/fixunder.sty | 48 + krb5-1-7/doc/implement/functions.sty | 70 + krb5-1-7/doc/implement/implement.tex | 94 + krb5-1-7/doc/implement/kdb-i.tex | 242 + krb5-1-7/doc/implement/keytab-i.tex | 204 + krb5-1-7/doc/implement/libos-i.tex | 34 + krb5-1-7/doc/implement/rcache-i.tex | 142 + krb5-1-7/doc/implementor.texinfo | 1247 ++ krb5-1-7/doc/install-old.texi | 2239 +++ krb5-1-7/doc/install.texinfo | 1563 ++ krb5-1-7/doc/iprop-notes.txt | 140 + krb5-1-7/doc/kadm5-errmsg.txt | 59 + krb5-1-7/doc/kadm5/adb-unit-test.tex | 134 + krb5-1-7/doc/kadm5/api-funcspec.tex | 2015 +++ krb5-1-7/doc/kadm5/api-server-design.tex | 1042 ++ krb5-1-7/doc/kadm5/api-unit-test.tex | 2679 +++ krb5-1-7/doc/kadm5/fullpage.sty | 9 + krb5-1-7/doc/kadm5/rcsid.sty | 5 + krb5-1-7/doc/kadm5acl.texinfo | 113 + krb5-1-7/doc/kadmin/README | 46 + .../draft-ietf-cat-kerb-chg-password-02.txt | 311 + krb5-1-7/doc/kadmin/kadmin.protocol | 382 + krb5-1-7/doc/kadmin/kpasswd.protocol | 303 + krb5-1-7/doc/kdcconf.texinfo | 24 + krb5-1-7/doc/kim/Doxyfile | 282 + krb5-1-7/doc/kim/html/doxygen.css | 358 + krb5-1-7/doc/kim/html/doxygen.png | Bin 0 -> 1281 bytes ...oup__kim__ccache__iterator__reference.html | 114 + .../html/group__kim__ccache__reference.html | 1217 ++ ..._kim__credential__iterator__reference.html | 124 + .../group__kim__credential__reference.html | 830 + .../html/group__kim__error__reference.html | 58 + ..._kim__favorite__identities__reference.html | 306 + .../html/group__kim__identity__reference.html | 589 + .../html/group__kim__library__reference.html | 225 + .../html/group__kim__options__reference.html | 776 + .../group__kim__preferences__reference.html | 989 ++ ...oup__kim__selection__hints__reference.html | 751 + .../html/group__kim__string__reference.html | 171 + .../html/group__kim__types__reference.html | 454 + krb5-1-7/doc/kim/html/index.html | 83 + .../doc/kim/html/kim_ccache_overview.html | 70 + .../doc/kim/html/kim_credential_overview.html | 67 + krb5-1-7/doc/kim/html/kim_error_overview.html | 16 + .../kim_favorite_identities_overview.html | 24 + .../doc/kim/html/kim_identity_overview.html | 43 + .../doc/kim/html/kim_options_overview.html | 40 + .../kim/html/kim_preferences_overview.html | 36 + .../html/kim_selection_hints_overview.html | 55 + .../doc/kim/html/kim_string_overview.html | 18 + krb5-1-7/doc/kim/html/modules.html | 25 + krb5-1-7/doc/kim/html/tab_b.gif | Bin 0 -> 35 bytes krb5-1-7/doc/kim/html/tab_l.gif | Bin 0 -> 706 bytes krb5-1-7/doc/kim/html/tab_r.gif | Bin 0 -> 2585 bytes krb5-1-7/doc/kim/html/tabs.css | 102 + .../draft-ietf-cat-kerberos-pk-init-09.txt | 908 + .../draft-jaganathan-rc4-hmac-03.txt | 1013 ++ krb5-1-7/doc/krb5-protocol/krb5.constants | 156 + krb5-1-7/doc/krb5-protocol/rfc3961.txt | 2803 +++ krb5-1-7/doc/krb5-protocol/rfc3962.txt | 899 + krb5-1-7/doc/krb5-protocol/rfc4120.txt | 7731 +++++++++ krb5-1-7/doc/krb5-protocol/rfc4121.txt | 1123 ++ krb5-1-7/doc/krb5-protocol/rfc4557.txt | 339 + krb5-1-7/doc/krb5conf.texinfo | 83 + krb5-1-7/doc/man2html | 608 + krb5-1-7/doc/man2html.M | 761 + krb5-1-7/doc/man2ps | 60 + krb5-1-7/doc/man2ps.M | 50 + krb5-1-7/doc/procedures.txt | 159 + krb5-1-7/doc/rpc/design.tex | 1037 ++ krb5-1-7/doc/salts.texinfo | 19 + krb5-1-7/doc/send-pr.texinfo | 144 + krb5-1-7/doc/support-enc.texinfo | 37 + krb5-1-7/doc/texinfo-suppl.tex | 7 + krb5-1-7/doc/texinfo.tex | 7226 ++++++++ krb5-1-7/doc/thread-safe.txt | 257 + krb5-1-7/doc/threads.txt | 101 + krb5-1-7/doc/user-guide.texinfo | 1705 ++ krb5-1-7/src/BADSYMS | 281 + krb5-1-7/src/Makefile.in | 637 + krb5-1-7/src/aclocal.m4 | 1773 ++ krb5-1-7/src/appl/Makefile.in | 8 + krb5-1-7/src/appl/bsd/Makefile.in | 84 + krb5-1-7/src/appl/bsd/configure.in | 159 + krb5-1-7/src/appl/bsd/defines.h | 85 + krb5-1-7/src/appl/bsd/deps | 78 + krb5-1-7/src/appl/bsd/forward.c | 76 + krb5-1-7/src/appl/bsd/getdtablesize.c | 19 + krb5-1-7/src/appl/bsd/kcmd.c | 1034 ++ krb5-1-7/src/appl/bsd/klogind.M | 174 + krb5-1-7/src/appl/bsd/krcp.c | 1362 ++ krb5-1-7/src/appl/bsd/krlogin.c | 1808 ++ krb5-1-7/src/appl/bsd/krlogind.c | 1430 ++ krb5-1-7/src/appl/bsd/krsh.c | 595 + krb5-1-7/src/appl/bsd/krshd.c | 2047 +++ krb5-1-7/src/appl/bsd/kshd.M | 211 + krb5-1-7/src/appl/bsd/login.M | 77 + krb5-1-7/src/appl/bsd/login.c | 1930 +++ krb5-1-7/src/appl/bsd/loginpaths.h | 113 + krb5-1-7/src/appl/bsd/rcp.M | 160 + krb5-1-7/src/appl/bsd/rlogin.M | 157 + krb5-1-7/src/appl/bsd/rpaths.h | 31 + krb5-1-7/src/appl/bsd/rsh.M | 173 + krb5-1-7/src/appl/bsd/setenv.c | 166 + krb5-1-7/src/appl/deps | 1 + krb5-1-7/src/appl/gss-sample/Makefile.in | 51 + krb5-1-7/src/appl/gss-sample/README | 163 + krb5-1-7/src/appl/gss-sample/deps | 12 + krb5-1-7/src/appl/gss-sample/gss-client.c | 812 + krb5-1-7/src/appl/gss-sample/gss-misc.c | 428 + krb5-1-7/src/appl/gss-sample/gss-misc.h | 60 + krb5-1-7/src/appl/gss-sample/gss-server.c | 793 + krb5-1-7/src/appl/gssftp/Makefile.in | 6 + krb5-1-7/src/appl/gssftp/README.gssftp | 45 + krb5-1-7/src/appl/gssftp/arpa/ftp.h | 128 + krb5-1-7/src/appl/gssftp/arpa/telnet.h | 310 + krb5-1-7/src/appl/gssftp/configure.in | 68 + krb5-1-7/src/appl/gssftp/deps | 1 + krb5-1-7/src/appl/gssftp/ftp/Makefile.in | 65 + krb5-1-7/src/appl/gssftp/ftp/cmds.c | 2533 +++ krb5-1-7/src/appl/gssftp/ftp/cmdtab.c | 209 + krb5-1-7/src/appl/gssftp/ftp/deps | 28 + krb5-1-7/src/appl/gssftp/ftp/domacro.c | 162 + krb5-1-7/src/appl/gssftp/ftp/ftp.M | 1127 ++ krb5-1-7/src/appl/gssftp/ftp/ftp.c | 2233 +++ krb5-1-7/src/appl/gssftp/ftp/ftp_var.h | 288 + krb5-1-7/src/appl/gssftp/ftp/getpass.c | 154 + krb5-1-7/src/appl/gssftp/ftp/glob.c | 784 + krb5-1-7/src/appl/gssftp/ftp/main.c | 606 + krb5-1-7/src/appl/gssftp/ftp/pathnames.h | 37 + krb5-1-7/src/appl/gssftp/ftp/pclose.c | 128 + krb5-1-7/src/appl/gssftp/ftp/radix.c | 166 + krb5-1-7/src/appl/gssftp/ftp/ruserpass.c | 293 + krb5-1-7/src/appl/gssftp/ftp/secure.c | 410 + krb5-1-7/src/appl/gssftp/ftp/secure.h | 19 + krb5-1-7/src/appl/gssftp/ftpd/CHANGES | 31 + krb5-1-7/src/appl/gssftp/ftpd/Makefile.in | 78 + krb5-1-7/src/appl/gssftp/ftpd/deps | 29 + krb5-1-7/src/appl/gssftp/ftpd/ftpcmd.y | 1532 ++ krb5-1-7/src/appl/gssftp/ftpd/ftpd.M | 501 + krb5-1-7/src/appl/gssftp/ftpd/ftpd.c | 2726 +++ krb5-1-7/src/appl/gssftp/ftpd/ftpd_var.h | 97 + krb5-1-7/src/appl/gssftp/ftpd/logwtmp.c | 90 + krb5-1-7/src/appl/gssftp/ftpd/pathnames.h | 36 + krb5-1-7/src/appl/gssftp/ftpd/popen.c | 194 + krb5-1-7/src/appl/gssftp/ftpd/secure.h | 19 + krb5-1-7/src/appl/gssftp/ftpd/vers.c | 38 + krb5-1-7/src/appl/libpty/Makefile.in | 112 + krb5-1-7/src/appl/libpty/README | 108 + krb5-1-7/src/appl/libpty/cleanup.c | 112 + krb5-1-7/src/appl/libpty/configure.in | 262 + krb5-1-7/src/appl/libpty/deps | 45 + krb5-1-7/src/appl/libpty/dump-utmp.c | 281 + krb5-1-7/src/appl/libpty/getpty.c | 149 + krb5-1-7/src/appl/libpty/init.c | 33 + krb5-1-7/src/appl/libpty/init_slave.c | 100 + krb5-1-7/src/appl/libpty/libpty.h | 54 + krb5-1-7/src/appl/libpty/logwtmp.c | 112 + krb5-1-7/src/appl/libpty/open_ctty.c | 67 + krb5-1-7/src/appl/libpty/open_slave.c | 101 + krb5-1-7/src/appl/libpty/pty-int.h | 138 + krb5-1-7/src/appl/libpty/pty_err.et | 50 + krb5-1-7/src/appl/libpty/pty_paranoia.c | 650 + krb5-1-7/src/appl/libpty/sane_hostname.c | 116 + krb5-1-7/src/appl/libpty/update_utmp.c | 724 + krb5-1-7/src/appl/libpty/update_wtmp.c | 127 + krb5-1-7/src/appl/libpty/vhangup.c | 50 + krb5-1-7/src/appl/libpty/void_assoc.c | 49 + krb5-1-7/src/appl/sample/Makefile.in | 5 + krb5-1-7/src/appl/sample/deps | 1 + krb5-1-7/src/appl/sample/sample.h | 36 + krb5-1-7/src/appl/sample/sclient/Makefile.in | 19 + krb5-1-7/src/appl/sample/sclient/deps | 1 + krb5-1-7/src/appl/sample/sclient/sclient.M | 38 + krb5-1-7/src/appl/sample/sclient/sclient.c | 260 + krb5-1-7/src/appl/sample/sserver/Makefile.in | 19 + krb5-1-7/src/appl/sample/sserver/deps | 1 + krb5-1-7/src/appl/sample/sserver/sserver.M | 130 + krb5-1-7/src/appl/sample/sserver/sserver.c | 245 + krb5-1-7/src/appl/simple/Makefile.in | 5 + krb5-1-7/src/appl/simple/client/Makefile.in | 19 + krb5-1-7/src/appl/simple/client/deps | 1 + krb5-1-7/src/appl/simple/client/sim_client.c | 338 + krb5-1-7/src/appl/simple/deps | 1 + krb5-1-7/src/appl/simple/server/Makefile.in | 20 + krb5-1-7/src/appl/simple/server/deps | 1 + krb5-1-7/src/appl/simple/server/sim_server.c | 279 + krb5-1-7/src/appl/simple/simple.h | 32 + krb5-1-7/src/appl/telnet/Config.generic | 830 + krb5-1-7/src/appl/telnet/Makefile.in | 5 + krb5-1-7/src/appl/telnet/README | 679 + krb5-1-7/src/appl/telnet/arpa/telnet.h | 327 + krb5-1-7/src/appl/telnet/configure.in | 164 + krb5-1-7/src/appl/telnet/deps | 1 + krb5-1-7/src/appl/telnet/kern.diff | 308 + .../src/appl/telnet/libtelnet/Makefile.in | 89 + .../src/appl/telnet/libtelnet/auth-proto.h | 98 + krb5-1-7/src/appl/telnet/libtelnet/auth.c | 651 + krb5-1-7/src/appl/telnet/libtelnet/auth.h | 85 + krb5-1-7/src/appl/telnet/libtelnet/deps | 38 + .../src/appl/telnet/libtelnet/enc-proto.h | 144 + krb5-1-7/src/appl/telnet/libtelnet/enc_des.c | 780 + krb5-1-7/src/appl/telnet/libtelnet/encrypt.c | 1014 ++ krb5-1-7/src/appl/telnet/libtelnet/encrypt.h | 103 + krb5-1-7/src/appl/telnet/libtelnet/forward.c | 78 + krb5-1-7/src/appl/telnet/libtelnet/genget.c | 102 + krb5-1-7/src/appl/telnet/libtelnet/getent.c | 71 + krb5-1-7/src/appl/telnet/libtelnet/getopt.c | 126 + krb5-1-7/src/appl/telnet/libtelnet/gettytab.c | 307 + krb5-1-7/src/appl/telnet/libtelnet/gettytab.h | 120 + krb5-1-7/src/appl/telnet/libtelnet/herror.c | 68 + .../src/appl/telnet/libtelnet/kerberos5.c | 901 + .../src/appl/telnet/libtelnet/key-proto.h | 66 + krb5-1-7/src/appl/telnet/libtelnet/krb5forw.h | 4 + krb5-1-7/src/appl/telnet/libtelnet/mem.c | 190 + .../src/appl/telnet/libtelnet/misc-proto.h | 88 + krb5-1-7/src/appl/telnet/libtelnet/misc.c | 96 + krb5-1-7/src/appl/telnet/libtelnet/misc.h | 46 + krb5-1-7/src/appl/telnet/libtelnet/parsetos.c | 42 + krb5-1-7/src/appl/telnet/libtelnet/setenv.c | 172 + krb5-1-7/src/appl/telnet/libtelnet/setsid.c | 49 + krb5-1-7/src/appl/telnet/libtelnet/spx.c | 592 + .../src/appl/telnet/libtelnet/strcasecmp.c | 121 + krb5-1-7/src/appl/telnet/libtelnet/strchr.c | 47 + krb5-1-7/src/appl/telnet/libtelnet/strdup.c | 62 + krb5-1-7/src/appl/telnet/libtelnet/strerror.c | 69 + krb5-1-7/src/appl/telnet/libtelnet/strftime.c | 307 + krb5-1-7/src/appl/telnet/libtelnet/strrchr.c | 47 + krb5-1-7/src/appl/telnet/stty.diff | 72 + krb5-1-7/src/appl/telnet/telnet.state | 80 + krb5-1-7/src/appl/telnet/telnet/Makefile.in | 74 + krb5-1-7/src/appl/telnet/telnet/authenc.c | 115 + krb5-1-7/src/appl/telnet/telnet/commands.c | 3189 ++++ krb5-1-7/src/appl/telnet/telnet/defines.h | 61 + krb5-1-7/src/appl/telnet/telnet/deps | 39 + krb5-1-7/src/appl/telnet/telnet/externs.h | 530 + krb5-1-7/src/appl/telnet/telnet/fdset.h | 49 + krb5-1-7/src/appl/telnet/telnet/general.h | 45 + krb5-1-7/src/appl/telnet/telnet/main.c | 341 + krb5-1-7/src/appl/telnet/telnet/network.c | 179 + krb5-1-7/src/appl/telnet/telnet/ring.c | 367 + krb5-1-7/src/appl/telnet/telnet/ring.h | 98 + krb5-1-7/src/appl/telnet/telnet/sys_bsd.c | 1208 ++ krb5-1-7/src/appl/telnet/telnet/telnet.0.ps | 1008 ++ krb5-1-7/src/appl/telnet/telnet/telnet.0.txt | 718 + krb5-1-7/src/appl/telnet/telnet/telnet.1 | 1339 ++ krb5-1-7/src/appl/telnet/telnet/telnet.c | 2760 +++ krb5-1-7/src/appl/telnet/telnet/terminal.c | 241 + krb5-1-7/src/appl/telnet/telnet/tmac.doc | 4102 +++++ krb5-1-7/src/appl/telnet/telnet/tn3270.c | 410 + krb5-1-7/src/appl/telnet/telnet/types.h | 52 + krb5-1-7/src/appl/telnet/telnet/utilities.c | 951 + krb5-1-7/src/appl/telnet/telnetd/ISSUES | 7 + krb5-1-7/src/appl/telnet/telnetd/Makefile.in | 84 + krb5-1-7/src/appl/telnet/telnetd/authenc.c | 86 + krb5-1-7/src/appl/telnet/telnetd/defs.h | 322 + krb5-1-7/src/appl/telnet/telnetd/deps | 58 + krb5-1-7/src/appl/telnet/telnetd/ext.h | 240 + krb5-1-7/src/appl/telnet/telnetd/global.c | 46 + krb5-1-7/src/appl/telnet/telnetd/pathnames.h | 55 + krb5-1-7/src/appl/telnet/telnetd/slc.c | 492 + krb5-1-7/src/appl/telnet/telnetd/state.c | 1676 ++ krb5-1-7/src/appl/telnet/telnetd/sys_term.c | 1494 ++ .../src/appl/telnet/telnetd/telnetd-ktd.c | 1462 ++ krb5-1-7/src/appl/telnet/telnetd/telnetd.0.ps | 555 + .../src/appl/telnet/telnetd/telnetd.0.txt | 322 + krb5-1-7/src/appl/telnet/telnetd/telnetd.8 | 631 + krb5-1-7/src/appl/telnet/telnetd/telnetd.c | 1715 ++ krb5-1-7/src/appl/telnet/telnetd/telnetd.h | 48 + krb5-1-7/src/appl/telnet/telnetd/termio-tn.c | 33 + krb5-1-7/src/appl/telnet/telnetd/termios-tn.c | 35 + krb5-1-7/src/appl/telnet/telnetd/termstat.c | 652 + krb5-1-7/src/appl/telnet/telnetd/utility.c | 1303 ++ krb5-1-7/src/appl/user_user/Makefile.in | 25 + krb5-1-7/src/appl/user_user/client.c | 278 + krb5-1-7/src/appl/user_user/deps | 1 + krb5-1-7/src/appl/user_user/server.c | 231 + krb5-1-7/src/ccapi/Makefile.in | 37 + krb5-1-7/src/ccapi/common/Makefile.in | 67 + .../src/ccapi/common/cci_array_internal.c | 314 + .../src/ccapi/common/cci_array_internal.h | 66 + krb5-1-7/src/ccapi/common/cci_common.h | 57 + krb5-1-7/src/ccapi/common/cci_cred_union.c | 1115 ++ krb5-1-7/src/ccapi/common/cci_cred_union.h | 53 + krb5-1-7/src/ccapi/common/cci_debugging.c | 55 + krb5-1-7/src/ccapi/common/cci_debugging.h | 44 + krb5-1-7/src/ccapi/common/cci_identifier.c | 291 + krb5-1-7/src/ccapi/common/cci_identifier.h | 65 + krb5-1-7/src/ccapi/common/cci_message.c | 214 + krb5-1-7/src/ccapi/common/cci_message.h | 53 + krb5-1-7/src/ccapi/common/cci_os_debugging.h | 35 + krb5-1-7/src/ccapi/common/cci_os_identifier.h | 34 + krb5-1-7/src/ccapi/common/cci_types.h | 103 + .../src/ccapi/common/mac/cci_os_debugging.c | 36 + .../src/ccapi/common/mac/cci_os_identifier.c | 80 + krb5-1-7/src/ccapi/common/unix/Makefile.in | 15 + .../src/ccapi/common/win/OldCC/autolock.hxx | 53 + .../src/ccapi/common/win/OldCC/ccutil.cxx | 187 + .../src/ccapi/common/win/OldCC/ccutil.def | 5 + krb5-1-7/src/ccapi/common/win/OldCC/ccutils.c | 140 + krb5-1-7/src/ccapi/common/win/OldCC/ccutils.h | 49 + krb5-1-7/src/ccapi/common/win/OldCC/init.cxx | 187 + krb5-1-7/src/ccapi/common/win/OldCC/init.hxx | 102 + krb5-1-7/src/ccapi/common/win/OldCC/name.h | 38 + krb5-1-7/src/ccapi/common/win/OldCC/opts.cxx | 188 + krb5-1-7/src/ccapi/common/win/OldCC/opts.hxx | 56 + .../src/ccapi/common/win/OldCC/secure.cxx | 161 + .../src/ccapi/common/win/OldCC/secure.hxx | 60 + krb5-1-7/src/ccapi/common/win/OldCC/util.cxx | 520 + krb5-1-7/src/ccapi/common/win/OldCC/util.h | 89 + .../src/ccapi/common/win/cci_os_debugging.c | 39 + .../src/ccapi/common/win/cci_os_identifier.c | 58 + krb5-1-7/src/ccapi/common/win/ccs_reply.Acf | 31 + krb5-1-7/src/ccapi/common/win/ccs_reply.Idl | 60 + krb5-1-7/src/ccapi/common/win/ccs_request.Acf | 31 + krb5-1-7/src/ccapi/common/win/ccs_request.idl | 58 + krb5-1-7/src/ccapi/common/win/tls.c | 106 + krb5-1-7/src/ccapi/common/win/tls.h | 73 + krb5-1-7/src/ccapi/common/win/win-utils.c | 69 + krb5-1-7/src/ccapi/common/win/win-utils.h | 55 + .../src/ccapi/doc/CCAPI-Windows-Design.html | 148 + krb5-1-7/src/ccapi/lib/Makefile.in | 65 + krb5-1-7/src/ccapi/lib/ccapi.exports | 1 + krb5-1-7/src/ccapi/lib/ccapi_ccache.c | 794 + krb5-1-7/src/ccapi/lib/ccapi_ccache.h | 106 + .../src/ccapi/lib/ccapi_ccache_iterator.c | 292 + .../src/ccapi/lib/ccapi_ccache_iterator.h | 52 + krb5-1-7/src/ccapi/lib/ccapi_context.c | 834 + krb5-1-7/src/ccapi/lib/ccapi_context.h | 87 + .../src/ccapi/lib/ccapi_context_change_time.c | 209 + .../src/ccapi/lib/ccapi_context_change_time.h | 42 + krb5-1-7/src/ccapi/lib/ccapi_credentials.c | 166 + krb5-1-7/src/ccapi/lib/ccapi_credentials.h | 44 + .../ccapi/lib/ccapi_credentials_iterator.c | 247 + .../ccapi/lib/ccapi_credentials_iterator.h | 52 + krb5-1-7/src/ccapi/lib/ccapi_err.et | 74 + krb5-1-7/src/ccapi/lib/ccapi_ipc.c | 120 + krb5-1-7/src/ccapi/lib/ccapi_ipc.h | 45 + krb5-1-7/src/ccapi/lib/ccapi_os_ipc.h | 39 + krb5-1-7/src/ccapi/lib/ccapi_string.c | 102 + krb5-1-7/src/ccapi/lib/ccapi_string.h | 37 + krb5-1-7/src/ccapi/lib/ccapi_v2.c | 918 + krb5-1-7/src/ccapi/lib/ccapi_v2.exports | 23 + krb5-1-7/src/ccapi/lib/mac/ccapi_os_ipc.c | 59 + krb5-1-7/src/ccapi/lib/mac/ccapi_vector.c | 839 + .../src/ccapi/lib/mac/ccapi_vector.exports | 59 + krb5-1-7/src/ccapi/lib/mac/ccapi_vector.h | 228 + krb5-1-7/src/ccapi/lib/unix/Makefile.in | 11 + krb5-1-7/src/ccapi/lib/win/Makefile.in | 119 + krb5-1-7/src/ccapi/lib/win/OldCC/ccapi.h | 284 + krb5-1-7/src/ccapi/lib/win/OldCC/client.cxx | 389 + krb5-1-7/src/ccapi/lib/win/OldCC/client.h | 61 + krb5-1-7/src/ccapi/lib/win/OldCC/rpc.cxx | 79 + krb5-1-7/src/ccapi/lib/win/WINCCAPI.sln | 20 + krb5-1-7/src/ccapi/lib/win/WINCCAPI.vcproj | 111 + krb5-1-7/src/ccapi/lib/win/ccapi_os_ipc.cxx | 379 + krb5-1-7/src/ccapi/lib/win/ccs_reply_proc.c | 96 + krb5-1-7/src/ccapi/lib/win/debug.exports | 13 + krb5-1-7/src/ccapi/lib/win/dllmain.cxx | 216 + krb5-1-7/src/ccapi/lib/win/dllmain.h | 42 + krb5-1-7/src/ccapi/server/Makefile.in | 62 + krb5-1-7/src/ccapi/server/ccs_array.c | 310 + krb5-1-7/src/ccapi/server/ccs_array.h | 133 + .../src/ccapi/server/ccs_cache_collection.c | 1110 ++ .../src/ccapi/server/ccs_cache_collection.h | 73 + krb5-1-7/src/ccapi/server/ccs_callback.c | 239 + krb5-1-7/src/ccapi/server/ccs_callback.h | 62 + krb5-1-7/src/ccapi/server/ccs_ccache.c | 1238 ++ krb5-1-7/src/ccapi/server/ccs_ccache.h | 83 + .../src/ccapi/server/ccs_ccache_iterator.c | 158 + .../src/ccapi/server/ccs_ccache_iterator.h | 38 + krb5-1-7/src/ccapi/server/ccs_client.c | 237 + krb5-1-7/src/ccapi/server/ccs_client.h | 53 + krb5-1-7/src/ccapi/server/ccs_common.h | 48 + krb5-1-7/src/ccapi/server/ccs_credentials.c | 140 + krb5-1-7/src/ccapi/server/ccs_credentials.h | 47 + .../ccapi/server/ccs_credentials_iterator.c | 160 + .../ccapi/server/ccs_credentials_iterator.h | 38 + krb5-1-7/src/ccapi/server/ccs_list.c | 362 + krb5-1-7/src/ccapi/server/ccs_list.h | 141 + krb5-1-7/src/ccapi/server/ccs_list_internal.c | 677 + krb5-1-7/src/ccapi/server/ccs_list_internal.h | 95 + krb5-1-7/src/ccapi/server/ccs_lock.c | 249 + krb5-1-7/src/ccapi/server/ccs_lock.h | 62 + krb5-1-7/src/ccapi/server/ccs_lock_state.c | 526 + krb5-1-7/src/ccapi/server/ccs_lock_state.h | 52 + krb5-1-7/src/ccapi/server/ccs_os_notify.h | 38 + krb5-1-7/src/ccapi/server/ccs_os_pipe.h | 43 + krb5-1-7/src/ccapi/server/ccs_os_server.h | 41 + krb5-1-7/src/ccapi/server/ccs_pipe.c | 59 + krb5-1-7/src/ccapi/server/ccs_pipe.h | 43 + krb5-1-7/src/ccapi/server/ccs_server.c | 402 + krb5-1-7/src/ccapi/server/ccs_server.h | 52 + krb5-1-7/src/ccapi/server/ccs_types.h | 121 + .../ccapi/server/mac/CCacheServerInfo.plist | 38 + krb5-1-7/src/ccapi/server/mac/ccs_os_notify.c | 80 + krb5-1-7/src/ccapi/server/mac/ccs_os_pipe.c | 81 + krb5-1-7/src/ccapi/server/mac/ccs_os_server.c | 98 + .../mac/edu.mit.Kerberos.CCacheServer.plist | 35 + krb5-1-7/src/ccapi/server/unix/Makefile.in | 15 + krb5-1-7/src/ccapi/server/win/Makefile.in | 110 + krb5-1-7/src/ccapi/server/win/Server.sln | 20 + krb5-1-7/src/ccapi/server/win/Server.vcproj | 227 + krb5-1-7/src/ccapi/server/win/WorkItem.cpp | 126 + krb5-1-7/src/ccapi/server/win/WorkQueue.cpp | 61 + krb5-1-7/src/ccapi/server/win/WorkQueue.h | 46 + krb5-1-7/src/ccapi/server/win/ccs_os_pipe.c | 64 + .../src/ccapi/server/win/ccs_os_server.cpp | 951 + .../src/ccapi/server/win/ccs_request_proc.c | 115 + krb5-1-7/src/ccapi/server/win/ccs_win_pipe.c | 165 + krb5-1-7/src/ccapi/server/win/ccs_win_pipe.h | 69 + krb5-1-7/src/ccapi/server/win/workitem.h | 48 + krb5-1-7/src/ccapi/test/Makefile.in | 229 + krb5-1-7/src/ccapi/test/Makefile.w32 | 75 + krb5-1-7/src/ccapi/test/Pingtest.sln | 20 + krb5-1-7/src/ccapi/test/main.c | 90 + krb5-1-7/src/ccapi/test/pingtest.c | 116 + krb5-1-7/src/ccapi/test/setlib.pl | 10 + krb5-1-7/src/ccapi/test/simple_lock_test.c | 91 + .../test_cc_ccache_clear_kdc_time_offset.c | 15 + .../src/ccapi/test/test_cc_ccache_compare.c | 15 + .../src/ccapi/test/test_cc_ccache_destroy.c | 15 + .../test/test_cc_ccache_get_change_time.c | 16 + .../test_cc_ccache_get_credentials_version.c | 16 + .../test/test_cc_ccache_get_kdc_time_offset.c | 16 + .../test_cc_ccache_get_last_default_time.c | 16 + .../src/ccapi/test/test_cc_ccache_get_name.c | 16 + .../ccapi/test/test_cc_ccache_get_principal.c | 16 + .../ccapi/test/test_cc_ccache_iterator_next.c | 16 + krb5-1-7/src/ccapi/test/test_cc_ccache_move.c | 16 + .../test_cc_ccache_new_credentials_iterator.c | 16 + .../src/ccapi/test/test_cc_ccache_release.c | 16 + .../test/test_cc_ccache_remove_credentials.c | 16 + .../ccapi/test/test_cc_ccache_set_default.c | 16 + .../test/test_cc_ccache_set_kdc_time_offset.c | 16 + .../ccapi/test/test_cc_ccache_set_principal.c | 16 + .../test/test_cc_ccache_store_credentials.c | 16 + krb5-1-7/src/ccapi/test/test_cc_close.c | 14 + .../src/ccapi/test/test_cc_context_compare.c | 16 + .../test/test_cc_context_create_ccache.c | 16 + .../test_cc_context_create_default_ccache.c | 16 + .../test/test_cc_context_create_new_ccache.c | 16 + .../test/test_cc_context_get_change_time.c | 16 + .../test_cc_context_get_default_ccache_name.c | 16 + .../test_cc_context_new_ccache_iterator.c | 16 + .../ccapi/test/test_cc_context_open_ccache.c | 16 + .../test_cc_context_open_default_ccache.c | 16 + .../src/ccapi/test/test_cc_context_release.c | 15 + krb5-1-7/src/ccapi/test/test_cc_create.c | 14 + .../test/test_cc_credentials_iterator_next.c | 15 + krb5-1-7/src/ccapi/test/test_cc_destroy.c | 14 + krb5-1-7/src/ccapi/test/test_cc_get_NC_info.c | 14 + .../src/ccapi/test/test_cc_get_change_time.c | 14 + .../src/ccapi/test/test_cc_get_cred_version.c | 14 + krb5-1-7/src/ccapi/test/test_cc_get_name.c | 14 + .../src/ccapi/test/test_cc_get_principal.c | 14 + krb5-1-7/src/ccapi/test/test_cc_initialize.c | 15 + krb5-1-7/src/ccapi/test/test_cc_open.c | 14 + krb5-1-7/src/ccapi/test/test_cc_remove_cred.c | 14 + .../ccapi/test/test_cc_seq_fetch_NCs_begin.c | 14 + .../ccapi/test/test_cc_seq_fetch_NCs_next.c | 14 + .../test/test_cc_seq_fetch_creds_begin.c | 14 + .../ccapi/test/test_cc_seq_fetch_creds_next.c | 14 + .../src/ccapi/test/test_cc_set_principal.c | 14 + krb5-1-7/src/ccapi/test/test_cc_shutdown.c | 14 + krb5-1-7/src/ccapi/test/test_cc_store.c | 14 + krb5-1-7/src/ccapi/test/test_ccapi.bat | 43 + krb5-1-7/src/ccapi/test/test_ccapi.sh | 76 + krb5-1-7/src/ccapi/test/test_ccapi_ccache.c | 2037 +++ krb5-1-7/src/ccapi/test/test_ccapi_ccache.h | 49 + krb5-1-7/src/ccapi/test/test_ccapi_check.c | 37 + krb5-1-7/src/ccapi/test/test_ccapi_check.h | 43 + .../src/ccapi/test/test_ccapi_constants.c | 66 + .../src/ccapi/test/test_ccapi_constants.h | 6 + krb5-1-7/src/ccapi/test/test_ccapi_context.c | 990 ++ krb5-1-7/src/ccapi/test/test_ccapi_context.h | 32 + krb5-1-7/src/ccapi/test/test_ccapi_globals.c | 87 + krb5-1-7/src/ccapi/test/test_ccapi_globals.h | 57 + .../src/ccapi/test/test_ccapi_iterators.c | 246 + .../src/ccapi/test/test_ccapi_iterators.h | 12 + krb5-1-7/src/ccapi/test/test_ccapi_log.c | 45 + krb5-1-7/src/ccapi/test/test_ccapi_log.h | 20 + krb5-1-7/src/ccapi/test/test_ccapi_util.c | 142 + krb5-1-7/src/ccapi/test/test_ccapi_util.h | 13 + krb5-1-7/src/ccapi/test/test_ccapi_v2.c | 1840 ++ krb5-1-7/src/ccapi/test/test_ccapi_v2.h | 73 + krb5-1-7/src/ccapi/test/test_constants.c | 15 + krb5-1-7/src/clients/Makefile.in | 55 + krb5-1-7/src/clients/deps | 1 + krb5-1-7/src/clients/kcpytkt/Makefile.in | 39 + krb5-1-7/src/clients/kcpytkt/kcpytkt.M | 37 + krb5-1-7/src/clients/kcpytkt/kcpytkt.c | 182 + krb5-1-7/src/clients/kdeltkt/Makefile.in | 39 + krb5-1-7/src/clients/kdeltkt/kdeltkt.M | 37 + krb5-1-7/src/clients/kdeltkt/kdeltkt.c | 174 + krb5-1-7/src/clients/kdestroy/Makefile.in | 41 + krb5-1-7/src/clients/kdestroy/deps | 6 + krb5-1-7/src/clients/kdestroy/kdestroy.M | 81 + krb5-1-7/src/clients/kdestroy/kdestroy.c | 150 + krb5-1-7/src/clients/kinit/Makefile.in | 44 + krb5-1-7/src/clients/kinit/deps | 7 + krb5-1-7/src/clients/kinit/kinit.M | 201 + krb5-1-7/src/clients/kinit/kinit.c | 742 + krb5-1-7/src/clients/klist/Makefile.in | 42 + krb5-1-7/src/clients/klist/deps | 8 + krb5-1-7/src/clients/klist/klist.M | 131 + krb5-1-7/src/clients/klist/klist.c | 671 + krb5-1-7/src/clients/kpasswd/Makefile.in | 44 + krb5-1-7/src/clients/kpasswd/deps | 10 + krb5-1-7/src/clients/kpasswd/kpasswd.M | 74 + krb5-1-7/src/clients/kpasswd/kpasswd.c | 159 + krb5-1-7/src/clients/kpasswd/ksetpwd.c | 314 + krb5-1-7/src/clients/ksu/Makefile.in | 43 + krb5-1-7/src/clients/ksu/authorization.c | 721 + krb5-1-7/src/clients/ksu/ccache.c | 818 + krb5-1-7/src/clients/ksu/deps | 67 + krb5-1-7/src/clients/ksu/heuristic.c | 765 + krb5-1-7/src/clients/ksu/krb_auth_su.c | 464 + krb5-1-7/src/clients/ksu/ksu.M | 481 + krb5-1-7/src/clients/ksu/ksu.h | 255 + krb5-1-7/src/clients/ksu/main.c | 998 ++ krb5-1-7/src/clients/ksu/setenv.c | 172 + krb5-1-7/src/clients/ksu/xmalloc.c | 84 + krb5-1-7/src/clients/kvno/Makefile.in | 42 + krb5-1-7/src/clients/kvno/deps | 6 + krb5-1-7/src/clients/kvno/kvno.M | 74 + krb5-1-7/src/clients/kvno/kvno.c | 278 + krb5-1-7/src/config-files/Makefile.in | 12 + .../src/config-files/convert-config-files | 84 + krb5-1-7/src/config-files/deps | 1 + krb5-1-7/src/config-files/kdc.conf | 13 + krb5-1-7/src/config-files/kdc.conf.M | 263 + krb5-1-7/src/config-files/krb5.conf | 26 + krb5-1-7/src/config-files/krb5.conf.M | 648 + krb5-1-7/src/config-files/mech | 3 + krb5-1-7/src/config-files/services.append | 32 + krb5-1-7/src/config/ac-archive/README | 51 + krb5-1-7/src/config/ac-archive/acx_pthread.m4 | 239 + krb5-1-7/src/config/config.guess | 1500 ++ krb5-1-7/src/config/config.sub | 1608 ++ krb5-1-7/src/config/install-sh | 295 + krb5-1-7/src/config/lib.in | 170 + krb5-1-7/src/config/libnodeps.in | 4 + krb5-1-7/src/config/libnover.in | 112 + krb5-1-7/src/config/libobj.in | 42 + krb5-1-7/src/config/libpriv.in | 13 + krb5-1-7/src/config/mkinstalldirs | 40 + krb5-1-7/src/config/move-if-changed | 17 + krb5-1-7/src/config/post.in | 207 + krb5-1-7/src/config/pre.in | 569 + krb5-1-7/src/config/ren2long | 9 + krb5-1-7/src/config/ren2long.awk | 75 + krb5-1-7/src/config/rm.bat | 32 + krb5-1-7/src/config/shlib.conf | 532 + krb5-1-7/src/config/wconfig.pl | 77 + krb5-1-7/src/config/win-post.in | 111 + krb5-1-7/src/config/win-pre.in | 259 + krb5-1-7/src/config/winexclude.sed | 19 + krb5-1-7/src/configure.in | 1100 ++ krb5-1-7/src/deps | 1 + krb5-1-7/src/gen-manpages/Makefile.in | 9 + krb5-1-7/src/gen-manpages/deps | 1 + krb5-1-7/src/gen-manpages/header.doc | 1 + krb5-1-7/src/gen-manpages/k5login.M | 55 + krb5-1-7/src/gen-manpages/kerberos.M | 143 + krb5-1-7/src/include/CredentialsCache.h | 1605 ++ krb5-1-7/src/include/CredentialsCache2.h | 326 + krb5-1-7/src/include/Makefile.in | 139 + krb5-1-7/src/include/adm.h | 222 + krb5-1-7/src/include/adm_proto.h | 139 + krb5-1-7/src/include/cm.h | 83 + krb5-1-7/src/include/copyright.h | 40 + krb5-1-7/src/include/deps | 1 + krb5-1-7/src/include/fake-addrinfo.h | 233 + krb5-1-7/src/include/foreachaddr.h | 64 + krb5-1-7/src/include/gssapi.h | 5 + krb5-1-7/src/include/gssrpc/auth.h | 219 + krb5-1-7/src/include/gssrpc/auth_gss.h | 149 + krb5-1-7/src/include/gssrpc/auth_gssapi.h | 153 + krb5-1-7/src/include/gssrpc/auth_unix.h | 80 + krb5-1-7/src/include/gssrpc/clnt.h | 344 + krb5-1-7/src/include/gssrpc/netdb.h | 51 + krb5-1-7/src/include/gssrpc/pmap_clnt.h | 81 + krb5-1-7/src/include/gssrpc/pmap_prot.h | 101 + krb5-1-7/src/include/gssrpc/pmap_rmt.h | 63 + krb5-1-7/src/include/gssrpc/rename.h | 309 + krb5-1-7/src/include/gssrpc/rpc.h | 99 + krb5-1-7/src/include/gssrpc/rpc_msg.h | 205 + krb5-1-7/src/include/gssrpc/svc.h | 341 + krb5-1-7/src/include/gssrpc/svc_auth.h | 117 + krb5-1-7/src/include/gssrpc/types.hin | 175 + krb5-1-7/src/include/gssrpc/xdr.h | 336 + krb5-1-7/src/include/iprop.h | 269 + krb5-1-7/src/include/iprop_hdr.h | 42 + krb5-1-7/src/include/k5-buf.h | 125 + krb5-1-7/src/include/k5-err.h | 98 + krb5-1-7/src/include/k5-gmt_mktime.h | 51 + krb5-1-7/src/include/k5-int-pkinit.h | 275 + krb5-1-7/src/include/k5-int.h | 2836 +++ krb5-1-7/src/include/k5-ipc_stream.h | 77 + krb5-1-7/src/include/k5-platform.h | 976 ++ krb5-1-7/src/include/k5-plugin.h | 109 + krb5-1-7/src/include/k5-thread.h | 454 + krb5-1-7/src/include/k5-unicode.h | 130 + krb5-1-7/src/include/k5-utf8.h | 249 + krb5-1-7/src/include/k5-util.h | 87 + krb5-1-7/src/include/kdb.h | 916 + krb5-1-7/src/include/kdb_ext.h | 169 + krb5-1-7/src/include/kdb_kt.h | 42 + krb5-1-7/src/include/kdb_log.h | 124 + krb5-1-7/src/include/kim/kim.h | 169 + krb5-1-7/src/include/kim/kim_ccache.h | 659 + krb5-1-7/src/include/kim/kim_credential.h | 568 + krb5-1-7/src/include/kim/kim_identity.h | 286 + krb5-1-7/src/include/kim/kim_library.h | 83 + krb5-1-7/src/include/kim/kim_options.h | 431 + krb5-1-7/src/include/kim/kim_preferences.h | 419 + .../src/include/kim/kim_selection_hints.h | 438 + krb5-1-7/src/include/kim/kim_string.h | 122 + krb5-1-7/src/include/kim/kim_types.h | 155 + krb5-1-7/src/include/kim/kim_ui_plugin.h | 152 + krb5-1-7/src/include/krb5.h | 7 + krb5-1-7/src/include/krb5/authdata_plugin.h | 160 + krb5-1-7/src/include/krb5/krb5.hin | 2633 +++ krb5-1-7/src/include/krb5/locate_plugin.h | 60 + krb5-1-7/src/include/krb5/preauth_plugin.h | 526 + krb5-1-7/src/include/krb54proto.h | 18 + krb5-1-7/src/include/osconf.hin | 140 + krb5-1-7/src/include/pkinit_apple_utils.h | 151 + krb5-1-7/src/include/pkinit_asn1.h | 172 + krb5-1-7/src/include/pkinit_cert_store.h | 163 + krb5-1-7/src/include/pkinit_client.h | 94 + krb5-1-7/src/include/pkinit_cms.h | 179 + krb5-1-7/src/include/port-sockets.h | 187 + krb5-1-7/src/include/socket-utils.h | 108 + krb5-1-7/src/include/spnego-asn1.h | 89 + krb5-1-7/src/include/win-mac.h | 229 + krb5-1-7/src/kadmin/Makefile.in | 8 + krb5-1-7/src/kadmin/cli/Makefile.in | 46 + krb5-1-7/src/kadmin/cli/deps | 41 + krb5-1-7/src/kadmin/cli/getdate.y | 1067 ++ krb5-1-7/src/kadmin/cli/k5srvutil.M | 58 + krb5-1-7/src/kadmin/cli/k5srvutil.sh | 117 + krb5-1-7/src/kadmin/cli/kadmin.M | 911 + krb5-1-7/src/kadmin/cli/kadmin.c | 1858 ++ krb5-1-7/src/kadmin/cli/kadmin.h | 75 + krb5-1-7/src/kadmin/cli/kadmin.local.M | 1 + krb5-1-7/src/kadmin/cli/kadmin_ct.ct | 85 + krb5-1-7/src/kadmin/cli/keytab.c | 490 + krb5-1-7/src/kadmin/cli/keytab_local.c | 9 + krb5-1-7/src/kadmin/cli/ss_wrapper.c | 64 + krb5-1-7/src/kadmin/cli/strftime.c | 464 + krb5-1-7/src/kadmin/dbutil/Makefile.in | 36 + krb5-1-7/src/kadmin/dbutil/deps | 168 + krb5-1-7/src/kadmin/dbutil/dump.c | 2590 +++ krb5-1-7/src/kadmin/dbutil/import_err.et | 22 + krb5-1-7/src/kadmin/dbutil/kadm5_create.c | 331 + krb5-1-7/src/kadmin/dbutil/kdb5_create.c | 513 + krb5-1-7/src/kadmin/dbutil/kdb5_destroy.c | 113 + krb5-1-7/src/kadmin/dbutil/kdb5_mkey.c | 1447 ++ krb5-1-7/src/kadmin/dbutil/kdb5_stash.c | 191 + krb5-1-7/src/kadmin/dbutil/kdb5_util.M | 273 + krb5-1-7/src/kadmin/dbutil/kdb5_util.c | 674 + krb5-1-7/src/kadmin/dbutil/kdb5_util.h | 104 + krb5-1-7/src/kadmin/dbutil/nstrtok.h | 3 + krb5-1-7/src/kadmin/dbutil/ovload.c | 211 + krb5-1-7/src/kadmin/dbutil/string_table.c | 84 + krb5-1-7/src/kadmin/dbutil/string_table.h | 39 + krb5-1-7/src/kadmin/dbutil/strtok.c | 105 + krb5-1-7/src/kadmin/deps | 1 + krb5-1-7/src/kadmin/kdbkeys/Makefile.in | 18 + krb5-1-7/src/kadmin/kdbkeys/do-test.pl | 56 + krb5-1-7/src/kadmin/ktutil/Makefile.in | 39 + krb5-1-7/src/kadmin/ktutil/deps | 26 + krb5-1-7/src/kadmin/ktutil/ktutil.M | 67 + krb5-1-7/src/kadmin/ktutil/ktutil.c | 280 + krb5-1-7/src/kadmin/ktutil/ktutil.h | 70 + krb5-1-7/src/kadmin/ktutil/ktutil_ct.ct | 59 + krb5-1-7/src/kadmin/ktutil/ktutil_funcs.c | 351 + krb5-1-7/src/kadmin/passwd/Kpasswd | 46 + krb5-1-7/src/kadmin/passwd/Makefile.in | 26 + krb5-1-7/src/kadmin/passwd/deps | 26 + krb5-1-7/src/kadmin/passwd/kpasswd.M | 70 + krb5-1-7/src/kadmin/passwd/kpasswd.c | 281 + krb5-1-7/src/kadmin/passwd/kpasswd.h | 46 + krb5-1-7/src/kadmin/passwd/kpasswd_strings.et | 76 + krb5-1-7/src/kadmin/passwd/tty_kpasswd.c | 81 + .../src/kadmin/passwd/unit-test/Makefile.in | 27 + .../kadmin/passwd/unit-test/config/unix.exp | 115 + krb5-1-7/src/kadmin/passwd/unit-test/deps | 1 + .../passwd/unit-test/kpasswd.0/changing.exp | 113 + .../passwd/unit-test/kpasswd.0/connecting.exp | 29 + .../passwd/unit-test/kpasswd.0/principal.exp | 87 + .../passwd/unit-test/kpasswd.0/usage.exp | 26 + .../kadmin/passwd/unit-test/lib/helpers.exp | 217 + krb5-1-7/src/kadmin/passwd/xm_kpasswd.c | 445 + krb5-1-7/src/kadmin/scripts/inst-hdrs.sh | 14 + krb5-1-7/src/kadmin/server/Makefile.in | 29 + krb5-1-7/src/kadmin/server/deps | 143 + krb5-1-7/src/kadmin/server/ipropd_svc.c | 611 + krb5-1-7/src/kadmin/server/kadm_rpc_svc.c | 338 + krb5-1-7/src/kadmin/server/kadmind.M | 296 + krb5-1-7/src/kadmin/server/misc.c | 225 + krb5-1-7/src/kadmin/server/misc.h | 97 + krb5-1-7/src/kadmin/server/network.c | 2039 +++ krb5-1-7/src/kadmin/server/ovsec_kadmd.c | 1056 ++ krb5-1-7/src/kadmin/server/schpw.c | 477 + krb5-1-7/src/kadmin/server/server_glue_v1.c | 32 + krb5-1-7/src/kadmin/server/server_stubs.c | 1662 ++ krb5-1-7/src/kadmin/testing/Makefile.in | 10 + krb5-1-7/src/kadmin/testing/deps | 1 + .../src/kadmin/testing/proto/kdc.conf.proto | 16 + .../src/kadmin/testing/proto/krb5.conf.proto | 30 + .../src/kadmin/testing/proto/ovsec_adm.dict | 3 + .../src/kadmin/testing/scripts/Makefile.in | 37 + .../kadmin/testing/scripts/compare_dump.plin | 242 + krb5-1-7/src/kadmin/testing/scripts/deps | 1 + .../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-7/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 | 220 + .../src/kadmin/testing/scripts/stop_servers | 62 + .../kadmin/testing/scripts/stop_servers_local | 53 + .../scripts/verify_xrunner_report.plin | 38 + krb5-1-7/src/kadmin/testing/tcl/util.t | 60 + krb5-1-7/src/kadmin/testing/util/Makefile.in | 44 + krb5-1-7/src/kadmin/testing/util/bsddb_dump.c | 64 + krb5-1-7/src/kadmin/testing/util/deps | 27 + krb5-1-7/src/kadmin/testing/util/tcl_kadm5.c | 2545 +++ krb5-1-7/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 | 2036 +++ .../kadmin/testing/util/tcl_ovsec_kadm_syntax | 57 + krb5-1-7/src/kadmin/testing/util/test.c | 38 + krb5-1-7/src/kdc/Makefile.in | 83 + krb5-1-7/src/kdc/deps | 145 + krb5-1-7/src/kdc/dispatch.c | 112 + krb5-1-7/src/kdc/do_as_req.c | 796 + krb5-1-7/src/kdc/do_tgs_req.c | 1190 ++ krb5-1-7/src/kdc/extern.c | 49 + krb5-1-7/src/kdc/extern.h | 110 + krb5-1-7/src/kdc/fast_util.c | 489 + krb5-1-7/src/kdc/kdc5_err.et | 35 + krb5-1-7/src/kdc/kdc_authdata.c | 617 + krb5-1-7/src/kdc/kdc_preauth.c | 3167 ++++ krb5-1-7/src/kdc/kdc_util.c | 2345 +++ krb5-1-7/src/kdc/kdc_util.h | 368 + krb5-1-7/src/kdc/krb5kdc.M | 168 + krb5-1-7/src/kdc/main.c | 922 + krb5-1-7/src/kdc/migration.doc | 59 + krb5-1-7/src/kdc/network.c | 1679 ++ krb5-1-7/src/kdc/pkinit_apple_server.c | 241 + krb5-1-7/src/kdc/pkinit_server.h | 112 + krb5-1-7/src/kdc/policy.c | 166 + krb5-1-7/src/kdc/policy.h | 39 + krb5-1-7/src/kdc/replay.c | 175 + krb5-1-7/src/kdc/rtest.c | 116 + krb5-1-7/src/kdc/rtest.good | 26 + krb5-1-7/src/kdc/rtscript | 54 + .../kim/agent/mac/AuthenticationController.h | 120 + .../kim/agent/mac/AuthenticationController.m | 678 + krb5-1-7/src/kim/agent/mac/BadgedImageView.h | 39 + krb5-1-7/src/kim/agent/mac/BadgedImageView.m | 104 + krb5-1-7/src/kim/agent/mac/IPCClient.h | 74 + krb5-1-7/src/kim/agent/mac/IPCClient.m | 338 + krb5-1-7/src/kim/agent/mac/Identities.h | 89 + krb5-1-7/src/kim/agent/mac/Identities.m | 849 + krb5-1-7/src/kim/agent/mac/KIMUtilities.h | 101 + krb5-1-7/src/kim/agent/mac/KIMUtilities.m | 376 + .../kim/agent/mac/KerberosAgent-Info.plist | 32 + .../kim/agent/mac/KerberosAgentController.h | 52 + .../kim/agent/mac/KerberosAgentController.m | 230 + .../src/kim/agent/mac/KerberosAgentListener.h | 109 + .../src/kim/agent/mac/KerberosAgentListener.m | 355 + .../src/kim/agent/mac/KerberosAgentPrefix.pch | 19 + .../src/kim/agent/mac/KerberosFormatters.h | 53 + .../src/kim/agent/mac/KerberosFormatters.m | 174 + krb5-1-7/src/kim/agent/mac/PopupButton.h | 34 + krb5-1-7/src/kim/agent/mac/PopupButton.m | 58 + .../kim/agent/mac/SelectIdentityController.h | 98 + .../kim/agent/mac/SelectIdentityController.m | 410 + krb5-1-7/src/kim/agent/mac/ServerDemux.h | 63 + krb5-1-7/src/kim/agent/mac/ServerDemux.m | 668 + .../mac/edu.mit.Kerberos.KerberosAgent.plist | 28 + krb5-1-7/src/kim/agent/mac/main.m | 6 + krb5-1-7/src/kim/agent/mac/resources/Add.tiff | Bin 0 -> 728 bytes .../kim/agent/mac/resources/Add_Pressed.tiff | Bin 0 -> 688 bytes .../English.lproj/Authentication.xib | 3866 +++++ .../AuthenticationController.strings | Bin 0 -> 2000 bytes .../mac/resources/English.lproj/MainMenu.xib | 791 + .../English.lproj/SelectIdentity.strings | Bin 0 -> 538 bytes .../English.lproj/SelectIdentity.xib | 2865 ++++ .../src/kim/agent/mac/resources/Gear.tiff | Bin 0 -> 22360 bytes .../agent/mac/resources/KerberosAgent.icns | Bin 0 -> 40494 bytes .../mac/resources/KerberosFormatters.strings | Bin 0 -> 3446 bytes .../src/kim/agent/mac/resources/Remove.tiff | Bin 0 -> 694 bytes .../agent/mac/resources/Remove_Pressed.tiff | Bin 0 -> 656 bytes krb5-1-7/src/kim/lib/kim-lite.exports | 133 + krb5-1-7/src/kim/lib/kim.exports | 152 + krb5-1-7/src/kim/lib/kim_ccache.c | 1265 ++ krb5-1-7/src/kim/lib/kim_credential.c | 1416 ++ krb5-1-7/src/kim/lib/kim_credential_private.h | 39 + krb5-1-7/src/kim/lib/kim_debug.c | 76 + krb5-1-7/src/kim/lib/kim_debug_private.h | 38 + krb5-1-7/src/kim/lib/kim_error_message.c | 245 + krb5-1-7/src/kim/lib/kim_error_private.h | 43 + krb5-1-7/src/kim/lib/kim_errors.et | 76 + krb5-1-7/src/kim/lib/kim_identity.c | 802 + krb5-1-7/src/kim/lib/kim_identity_private.h | 66 + krb5-1-7/src/kim/lib/kim_library.c | 403 + krb5-1-7/src/kim/lib/kim_library_private.h | 52 + krb5-1-7/src/kim/lib/kim_options.c | 670 + krb5-1-7/src/kim/lib/kim_options_private.h | 51 + krb5-1-7/src/kim/lib/kim_preferences.c | 1088 ++ .../src/kim/lib/kim_preferences_private.h | 126 + krb5-1-7/src/kim/lib/kim_private.h | 52 + krb5-1-7/src/kim/lib/kim_selection_hints.c | 787 + .../src/kim/lib/kim_selection_hints_private.h | 66 + krb5-1-7/src/kim/lib/kim_string.c | 183 + krb5-1-7/src/kim/lib/kim_string_private.h | 68 + krb5-1-7/src/kim/lib/kim_ui.c | 550 + krb5-1-7/src/kim/lib/kim_ui_cli.c | 478 + krb5-1-7/src/kim/lib/kim_ui_cli_private.h | 80 + krb5-1-7/src/kim/lib/kim_ui_gui_private.h | 80 + krb5-1-7/src/kim/lib/kim_ui_plugin.c | 354 + krb5-1-7/src/kim/lib/kim_ui_plugin_private.h | 77 + krb5-1-7/src/kim/lib/kim_ui_private.h | 101 + krb5-1-7/src/kim/lib/mac/KerberosLogin.c | 1860 ++ .../src/kim/lib/mac/KerberosLogin.exports | 107 + krb5-1-7/src/kim/lib/mac/KerberosLogin.h | 456 + .../src/kim/lib/mac/KerberosLoginErrors.et | 88 + .../src/kim/lib/mac/KerberosLoginPrivate.h | 123 + krb5-1-7/src/kim/lib/mac/kim_os_debug.c | 37 + krb5-1-7/src/kim/lib/mac/kim_os_identity.c | 314 + krb5-1-7/src/kim/lib/mac/kim_os_library.c | 332 + krb5-1-7/src/kim/lib/mac/kim_os_preferences.c | 1073 ++ krb5-1-7/src/kim/lib/mac/kim_os_private.h | 56 + .../src/kim/lib/mac/kim_os_selection_hints.c | 536 + krb5-1-7/src/kim/lib/mac/kim_os_string.c | 237 + krb5-1-7/src/kim/lib/mac/kim_os_ui_gui.c | 563 + krb5-1-7/src/kim/test/main.c | 78 + krb5-1-7/src/kim/test/test_kim_common.c | 138 + krb5-1-7/src/kim/test/test_kim_common.h | 68 + krb5-1-7/src/kim/test/test_kim_identity.c | 595 + krb5-1-7/src/kim/test/test_kim_identity.h | 52 + krb5-1-7/src/kim/test/test_kim_preferences.c | 918 + krb5-1-7/src/kim/test/test_kim_preferences.h | 46 + .../src/kim/test/test_kim_selection_hints.c | 178 + .../src/kim/test/test_kim_selection_hints.h | 36 + krb5-1-7/src/kim/test/test_kll.c | 556 + krb5-1-7/src/kim/test/test_kll_terminal.c | 39 + krb5-1-7/src/kim/test/test_ui_plugin.c | 472 + krb5-1-7/src/krb5-config.M | 73 + krb5-1-7/src/krb5-config.in | 223 + krb5-1-7/src/lib/Makefile.in | 194 + krb5-1-7/src/lib/apputils/Makefile.in | 38 + krb5-1-7/src/lib/apputils/daemon.c | 95 + krb5-1-7/src/lib/apputils/deps | 14 + krb5-1-7/src/lib/apputils/dummy.c | 1 + krb5-1-7/src/lib/comerr32.def | 12 + krb5-1-7/src/lib/crypto/ISSUES | 16 + krb5-1-7/src/lib/crypto/Makefile.in | 403 + krb5-1-7/src/lib/crypto/aead.c | 573 + krb5-1-7/src/lib/crypto/aead.h | 123 + krb5-1-7/src/lib/crypto/aes/Makefile.in | 72 + krb5-1-7/src/lib/crypto/aes/aes-gen.c | 326 + krb5-1-7/src/lib/crypto/aes/aes-test.c | 138 + krb5-1-7/src/lib/crypto/aes/aes.h | 97 + krb5-1-7/src/lib/crypto/aes/aes.txt | 70 + krb5-1-7/src/lib/crypto/aes/aes_s2k.c | 90 + krb5-1-7/src/lib/crypto/aes/aes_s2k.h | 4 + krb5-1-7/src/lib/crypto/aes/aescpp.h | 55 + krb5-1-7/src/lib/crypto/aes/aescrypp.c | 487 + krb5-1-7/src/lib/crypto/aes/aescrypt.asm | 402 + krb5-1-7/src/lib/crypto/aes/aescrypt.c | 421 + krb5-1-7/src/lib/crypto/aes/aeskey.c | 369 + krb5-1-7/src/lib/crypto/aes/aeskeypp.c | 399 + krb5-1-7/src/lib/crypto/aes/aesopt.h | 851 + krb5-1-7/src/lib/crypto/aes/aessrc.url | 1 + krb5-1-7/src/lib/crypto/aes/aestab.c | 494 + krb5-1-7/src/lib/crypto/aes/deps | 20 + krb5-1-7/src/lib/crypto/aes/expect-vk.txt | 1548 ++ krb5-1-7/src/lib/crypto/aes/expect-vt.txt | 1036 ++ krb5-1-7/src/lib/crypto/aes/test/Readme.txt | 22 + krb5-1-7/src/lib/crypto/aes/test/cbc_d_m.txt | 7224 ++++++++ krb5-1-7/src/lib/crypto/aes/test/cbc_e_m.txt | 7224 ++++++++ krb5-1-7/src/lib/crypto/aes/test/ecb_d_m.txt | 6024 +++++++ krb5-1-7/src/lib/crypto/aes/test/ecb_e_m.txt | 6024 +++++++ .../src/lib/crypto/aes/test/ecb_iv.readme | 19 + krb5-1-7/src/lib/crypto/aes/test/ecb_iv.txt | 123 + krb5-1-7/src/lib/crypto/aes/test/ecb_tbl.txt | 1955 +++ krb5-1-7/src/lib/crypto/aes/test/ecb_vk.txt | 2334 +++ krb5-1-7/src/lib/crypto/aes/test/ecb_vt.txt | 1566 ++ krb5-1-7/src/lib/crypto/aes/test/katmct.pdf | Bin 0 -> 100812 bytes krb5-1-7/src/lib/crypto/aes/uitypes.h | 83 + krb5-1-7/src/lib/crypto/aes/vb.txt | 87 + krb5-1-7/src/lib/crypto/arcfour/Makefile.in | 43 + krb5-1-7/src/lib/crypto/arcfour/arcfour-int.h | 32 + krb5-1-7/src/lib/crypto/arcfour/arcfour.c | 340 + krb5-1-7/src/lib/crypto/arcfour/arcfour.h | 43 + .../src/lib/crypto/arcfour/arcfour_aead.c | 325 + krb5-1-7/src/lib/crypto/arcfour/arcfour_s2k.c | 59 + krb5-1-7/src/lib/crypto/arcfour/deps | 37 + krb5-1-7/src/lib/crypto/block_size.c | 47 + krb5-1-7/src/lib/crypto/cf2.c | 154 + krb5-1-7/src/lib/crypto/checksum_length.c | 53 + krb5-1-7/src/lib/crypto/cksumtype_to_string.c | 45 + krb5-1-7/src/lib/crypto/cksumtypes.c | 91 + krb5-1-7/src/lib/crypto/cksumtypes.h | 62 + krb5-1-7/src/lib/crypto/coll_proof_cksum.c | 50 + krb5-1-7/src/lib/crypto/combine_keys.c | 349 + krb5-1-7/src/lib/crypto/crc32/CRC.pm | 156 + krb5-1-7/src/lib/crypto/crc32/Makefile.in | 41 + krb5-1-7/src/lib/crypto/crc32/Poly.pm | 182 + krb5-1-7/src/lib/crypto/crc32/crc-32.h | 71 + krb5-1-7/src/lib/crypto/crc32/crc.pl | 111 + krb5-1-7/src/lib/crypto/crc32/crc32.c | 192 + krb5-1-7/src/lib/crypto/crc32/deps | 13 + krb5-1-7/src/lib/crypto/crc32/t_crc.c | 213 + krb5-1-7/src/lib/crypto/crypto_length.c | 170 + krb5-1-7/src/lib/crypto/crypto_libinit.c | 33 + krb5-1-7/src/lib/crypto/decrypt.c | 67 + krb5-1-7/src/lib/crypto/decrypt_iov.c | 61 + krb5-1-7/src/lib/crypto/default_state.c | 63 + krb5-1-7/src/lib/crypto/deps | 535 + krb5-1-7/src/lib/crypto/des/ISSUES | 13 + krb5-1-7/src/lib/crypto/des/Makefile.in | 104 + krb5-1-7/src/lib/crypto/des/afsstring2key.c | 570 + krb5-1-7/src/lib/crypto/des/d3_aead.c | 207 + krb5-1-7/src/lib/crypto/des/d3_cbc.c | 223 + krb5-1-7/src/lib/crypto/des/d3_kysched.c | 50 + krb5-1-7/src/lib/crypto/des/deps | 146 + krb5-1-7/src/lib/crypto/des/des_int.h | 382 + krb5-1-7/src/lib/crypto/des/des_prf.c | 54 + krb5-1-7/src/lib/crypto/des/destest.c | 247 + krb5-1-7/src/lib/crypto/des/doc/libdes.doc | 208 + krb5-1-7/src/lib/crypto/des/f_aead.c | 195 + krb5-1-7/src/lib/crypto/des/f_cbc.c | 274 + krb5-1-7/src/lib/crypto/des/f_cksum.c | 136 + krb5-1-7/src/lib/crypto/des/f_parity.c | 56 + krb5-1-7/src/lib/crypto/des/f_sched.c | 359 + krb5-1-7/src/lib/crypto/des/f_tables.c | 370 + krb5-1-7/src/lib/crypto/des/f_tables.h | 279 + krb5-1-7/src/lib/crypto/des/key_sched.c | 61 + krb5-1-7/src/lib/crypto/des/keytest.data | 171 + krb5-1-7/src/lib/crypto/des/string2key.c | 261 + krb5-1-7/src/lib/crypto/des/t_afss2k.c | 136 + krb5-1-7/src/lib/crypto/des/t_verify.c | 418 + krb5-1-7/src/lib/crypto/des/weak_key.c | 85 + krb5-1-7/src/lib/crypto/dk/Makefile.in | 55 + krb5-1-7/src/lib/crypto/dk/checksum.c | 168 + krb5-1-7/src/lib/crypto/dk/deps | 76 + krb5-1-7/src/lib/crypto/dk/derive.c | 217 + krb5-1-7/src/lib/crypto/dk/dk.h | 124 + krb5-1-7/src/lib/crypto/dk/dk_aead.c | 381 + krb5-1-7/src/lib/crypto/dk/dk_decrypt.c | 206 + krb5-1-7/src/lib/crypto/dk/dk_encrypt.c | 358 + krb5-1-7/src/lib/crypto/dk/dk_prf.c | 64 + krb5-1-7/src/lib/crypto/dk/stringtokey.c | 96 + .../src/lib/crypto/enc_provider/Makefile.in | 42 + krb5-1-7/src/lib/crypto/enc_provider/aes.c | 422 + krb5-1-7/src/lib/crypto/enc_provider/deps | 48 + krb5-1-7/src/lib/crypto/enc_provider/des.c | 181 + krb5-1-7/src/lib/crypto/enc_provider/des3.c | 221 + .../lib/crypto/enc_provider/enc_provider.h | 36 + krb5-1-7/src/lib/crypto/enc_provider/rc4.c | 271 + krb5-1-7/src/lib/crypto/encrypt.c | 63 + krb5-1-7/src/lib/crypto/encrypt_iov.c | 55 + krb5-1-7/src/lib/crypto/encrypt_length.c | 59 + krb5-1-7/src/lib/crypto/enctype_compare.c | 55 + krb5-1-7/src/lib/crypto/enctype_to_string.c | 45 + krb5-1-7/src/lib/crypto/etypes.c | 169 + krb5-1-7/src/lib/crypto/etypes.h | 83 + .../src/lib/crypto/hash_provider/Makefile.in | 37 + krb5-1-7/src/lib/crypto/hash_provider/deps | 47 + .../src/lib/crypto/hash_provider/hash_crc32.c | 55 + .../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 | 57 + krb5-1-7/src/lib/crypto/hmac.c | 166 + krb5-1-7/src/lib/crypto/keyblocks.c | 79 + .../src/lib/crypto/keyed_checksum_types.c | 89 + krb5-1-7/src/lib/crypto/keyed_cksum.c | 55 + .../lib/crypto/keyhash_provider/Makefile.in | 56 + krb5-1-7/src/lib/crypto/keyhash_provider/deps | 60 + .../src/lib/crypto/keyhash_provider/descbc.c | 72 + .../lib/crypto/keyhash_provider/hmac_md5.c | 144 + .../lib/crypto/keyhash_provider/k5_md4des.c | 194 + .../lib/crypto/keyhash_provider/k5_md5des.c | 191 + .../keyhash_provider/keyhash_provider.h | 35 + .../lib/crypto/keyhash_provider/md5_hmac.c | 65 + .../src/lib/crypto/keyhash_provider/t_cksum.c | 180 + krb5-1-7/src/lib/crypto/keylengths.c | 61 + krb5-1-7/src/lib/crypto/libk5crypto.exports | 162 + krb5-1-7/src/lib/crypto/make_checksum.c | 129 + krb5-1-7/src/lib/crypto/make_checksum_iov.c | 82 + krb5-1-7/src/lib/crypto/make_random_key.c | 83 + krb5-1-7/src/lib/crypto/mandatory_sumtype.c | 41 + krb5-1-7/src/lib/crypto/md4/ISSUES | 3 + krb5-1-7/src/lib/crypto/md4/Makefile.in | 58 + krb5-1-7/src/lib/crypto/md4/deps | 13 + krb5-1-7/src/lib/crypto/md4/md4.c | 246 + krb5-1-7/src/lib/crypto/md4/rsa-md4.h | 94 + krb5-1-7/src/lib/crypto/md5/ISSUES | 3 + krb5-1-7/src/lib/crypto/md5/Makefile.in | 48 + krb5-1-7/src/lib/crypto/md5/deps | 13 + krb5-1-7/src/lib/crypto/md5/md5.c | 343 + krb5-1-7/src/lib/crypto/md5/rsa-md5.h | 60 + krb5-1-7/src/lib/crypto/md5/t_cksum.c | 206 + krb5-1-7/src/lib/crypto/md5/t_mddriver.c | 323 + krb5-1-7/src/lib/crypto/nfold.c | 130 + krb5-1-7/src/lib/crypto/old/Makefile.in | 35 + krb5-1-7/src/lib/crypto/old/deps | 34 + krb5-1-7/src/lib/crypto/old/des_stringtokey.c | 58 + krb5-1-7/src/lib/crypto/old/old.h | 52 + krb5-1-7/src/lib/crypto/old/old_decrypt.c | 145 + krb5-1-7/src/lib/crypto/old/old_encrypt.c | 110 + krb5-1-7/src/lib/crypto/old_api_glue.c | 328 + krb5-1-7/src/lib/crypto/pbkdf2.c | 265 + krb5-1-7/src/lib/crypto/prf.c | 87 + krb5-1-7/src/lib/crypto/prng.c | 215 + krb5-1-7/src/lib/crypto/random_to_key.c | 73 + krb5-1-7/src/lib/crypto/raw/Makefile.in | 34 + krb5-1-7/src/lib/crypto/raw/deps | 34 + krb5-1-7/src/lib/crypto/raw/raw.h | 49 + krb5-1-7/src/lib/crypto/raw/raw_aead.c | 163 + krb5-1-7/src/lib/crypto/raw/raw_decrypt.c | 40 + krb5-1-7/src/lib/crypto/raw/raw_encrypt.c | 50 + krb5-1-7/src/lib/crypto/sha1/ISSUES | 7 + krb5-1-7/src/lib/crypto/sha1/Makefile.in | 53 + krb5-1-7/src/lib/crypto/sha1/deps | 13 + krb5-1-7/src/lib/crypto/sha1/shs.c | 381 + krb5-1-7/src/lib/crypto/sha1/shs.h | 45 + krb5-1-7/src/lib/crypto/sha1/t_shs.c | 135 + krb5-1-7/src/lib/crypto/sha1/t_shs3.c | 592 + krb5-1-7/src/lib/crypto/state.c | 72 + krb5-1-7/src/lib/crypto/string_to_cksumtype.c | 53 + krb5-1-7/src/lib/crypto/string_to_enctype.c | 53 + krb5-1-7/src/lib/crypto/string_to_key.c | 101 + krb5-1-7/src/lib/crypto/t_cf2.c | 88 + krb5-1-7/src/lib/crypto/t_cf2.comments | 5 + krb5-1-7/src/lib/crypto/t_cf2.expected | 4 + krb5-1-7/src/lib/crypto/t_cf2.in | 20 + krb5-1-7/src/lib/crypto/t_cts.c | 176 + krb5-1-7/src/lib/crypto/t_encrypt.c | 214 + krb5-1-7/src/lib/crypto/t_hmac.c | 273 + krb5-1-7/src/lib/crypto/t_nfold.c | 165 + krb5-1-7/src/lib/crypto/t_pkcs5.c | 105 + krb5-1-7/src/lib/crypto/t_prf.c | 91 + krb5-1-7/src/lib/crypto/t_prf.comments | 8 + krb5-1-7/src/lib/crypto/t_prf.expected | 6 + krb5-1-7/src/lib/crypto/t_prf.in | 18 + krb5-1-7/src/lib/crypto/t_prng.c | 87 + krb5-1-7/src/lib/crypto/t_prng.comments | 14 + krb5-1-7/src/lib/crypto/t_prng.expected | 4 + krb5-1-7/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-7/src/lib/crypto/t_prng.seed | 25 + krb5-1-7/src/lib/crypto/t_short.c | 126 + krb5-1-7/src/lib/crypto/valid_cksumtype.c | 47 + krb5-1-7/src/lib/crypto/valid_enctype.c | 68 + krb5-1-7/src/lib/crypto/vectors.c | 457 + krb5-1-7/src/lib/crypto/verify_checksum.c | 92 + krb5-1-7/src/lib/crypto/verify_checksum_iov.c | 98 + krb5-1-7/src/lib/crypto/yarrow/ASSUMPTIONS | 101 + krb5-1-7/src/lib/crypto/yarrow/LICENSE | 21 + krb5-1-7/src/lib/crypto/yarrow/Makefile.in | 39 + krb5-1-7/src/lib/crypto/yarrow/README | 94 + krb5-1-7/src/lib/crypto/yarrow/TODO | 9 + krb5-1-7/src/lib/crypto/yarrow/deps | 25 + krb5-1-7/src/lib/crypto/yarrow/yarrow.c | 958 ++ krb5-1-7/src/lib/crypto/yarrow/yarrow.h | 186 + krb5-1-7/src/lib/crypto/yarrow/yarrow.man | 315 + krb5-1-7/src/lib/crypto/yarrow/yarrow.pod | 112 + krb5-1-7/src/lib/crypto/yarrow/ycipher.c | 96 + krb5-1-7/src/lib/crypto/yarrow/ycipher.h | 42 + krb5-1-7/src/lib/crypto/yarrow/yexcep.h | 107 + krb5-1-7/src/lib/crypto/yarrow/yhash.h | 29 + krb5-1-7/src/lib/crypto/yarrow/ylock.h | 24 + krb5-1-7/src/lib/crypto/yarrow/ystate.h | 28 + krb5-1-7/src/lib/crypto/yarrow/ytest.c | 385 + krb5-1-7/src/lib/crypto/yarrow/ytypes.h | 27 + krb5-1-7/src/lib/deps | 1 + krb5-1-7/src/lib/glue4.c | 19 + krb5-1-7/src/lib/gssapi/LICENSE | 91 + krb5-1-7/src/lib/gssapi/Makefile.in | 137 + krb5-1-7/src/lib/gssapi/README_SAMPLE_APP | 4 + krb5-1-7/src/lib/gssapi/deps | 1 + krb5-1-7/src/lib/gssapi/generic/Makefile.in | 173 + krb5-1-7/src/lib/gssapi/generic/deps | 73 + .../lib/gssapi/generic/disp_com_err_status.c | 64 + .../lib/gssapi/generic/disp_major_status.c | 310 + krb5-1-7/src/lib/gssapi/generic/gssapi.hin | 803 + .../src/lib/gssapi/generic/gssapiP_generic.h | 297 + .../lib/gssapi/generic/gssapi_err_generic.et | 49 + krb5-1-7/src/lib/gssapi/generic/gssapi_ext.h | 261 + .../src/lib/gssapi/generic/gssapi_generic.c | 155 + .../src/lib/gssapi/generic/gssapi_generic.h | 59 + krb5-1-7/src/lib/gssapi/generic/maptest.c | 68 + krb5-1-7/src/lib/gssapi/generic/oid_ops.c | 569 + krb5-1-7/src/lib/gssapi/generic/rel_buffer.c | 57 + krb5-1-7/src/lib/gssapi/generic/rel_oid_set.c | 61 + krb5-1-7/src/lib/gssapi/generic/util_buffer.c | 45 + .../src/lib/gssapi/generic/util_buffer_set.c | 126 + .../src/lib/gssapi/generic/util_canonhost.c | 69 + krb5-1-7/src/lib/gssapi/generic/util_errmap.c | 276 + .../src/lib/gssapi/generic/util_localhost.c | 49 + .../src/lib/gssapi/generic/util_ordering.c | 252 + krb5-1-7/src/lib/gssapi/generic/util_set.c | 106 + krb5-1-7/src/lib/gssapi/generic/util_token.c | 230 + .../src/lib/gssapi/generic/util_validate.c | 314 + .../lib/gssapi/generic/utl_nohash_validate.c | 121 + krb5-1-7/src/lib/gssapi/krb5/3des.txt | 395 + krb5-1-7/src/lib/gssapi/krb5/Makefile.in | 273 + .../src/lib/gssapi/krb5/accept_sec_context.c | 1232 ++ krb5-1-7/src/lib/gssapi/krb5/acquire_cred.c | 761 + krb5-1-7/src/lib/gssapi/krb5/add_cred.c | 388 + krb5-1-7/src/lib/gssapi/krb5/canon_name.c | 46 + krb5-1-7/src/lib/gssapi/krb5/compare_name.c | 61 + krb5-1-7/src/lib/gssapi/krb5/context_time.c | 69 + krb5-1-7/src/lib/gssapi/krb5/copy_ccache.c | 65 + .../src/lib/gssapi/krb5/delete_sec_context.c | 125 + krb5-1-7/src/lib/gssapi/krb5/deps | 657 + krb5-1-7/src/lib/gssapi/krb5/disp_name.c | 76 + krb5-1-7/src/lib/gssapi/krb5/disp_status.c | 197 + krb5-1-7/src/lib/gssapi/krb5/duplicate_name.c | 75 + krb5-1-7/src/lib/gssapi/krb5/export_name.c | 97 + .../src/lib/gssapi/krb5/export_sec_context.c | 107 + krb5-1-7/src/lib/gssapi/krb5/get_tkt_flags.c | 45 + krb5-1-7/src/lib/gssapi/krb5/gssapiP_krb5.h | 933 + .../src/lib/gssapi/krb5/gssapi_err_krb5.et | 40 + krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.c | 799 + krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.hin | 288 + krb5-1-7/src/lib/gssapi/krb5/import_name.c | 254 + .../src/lib/gssapi/krb5/import_sec_context.c | 129 + krb5-1-7/src/lib/gssapi/krb5/indicate_mechs.c | 37 + .../src/lib/gssapi/krb5/init_sec_context.c | 1017 ++ krb5-1-7/src/lib/gssapi/krb5/inq_context.c | 313 + krb5-1-7/src/lib/gssapi/krb5/inq_cred.c | 268 + krb5-1-7/src/lib/gssapi/krb5/inq_names.c | 99 + krb5-1-7/src/lib/gssapi/krb5/k5seal.c | 399 + krb5-1-7/src/lib/gssapi/krb5/k5sealiov.c | 511 + krb5-1-7/src/lib/gssapi/krb5/k5sealv3.c | 524 + krb5-1-7/src/lib/gssapi/krb5/k5sealv3iov.c | 469 + krb5-1-7/src/lib/gssapi/krb5/k5unseal.c | 561 + krb5-1-7/src/lib/gssapi/krb5/k5unsealiov.c | 665 + krb5-1-7/src/lib/gssapi/krb5/krb5_gss_glue.c | 418 + krb5-1-7/src/lib/gssapi/krb5/lucid_context.c | 303 + .../lib/gssapi/krb5/process_context_token.c | 65 + krb5-1-7/src/lib/gssapi/krb5/rel_cred.c | 96 + krb5-1-7/src/lib/gssapi/krb5/rel_name.c | 55 + krb5-1-7/src/lib/gssapi/krb5/rel_oid.c | 86 + krb5-1-7/src/lib/gssapi/krb5/seal.c | 82 + krb5-1-7/src/lib/gssapi/krb5/ser_sctx.c | 747 + .../lib/gssapi/krb5/set_allowable_enctypes.c | 138 + krb5-1-7/src/lib/gssapi/krb5/set_ccache.c | 100 + krb5-1-7/src/lib/gssapi/krb5/sign.c | 77 + krb5-1-7/src/lib/gssapi/krb5/unseal.c | 67 + krb5-1-7/src/lib/gssapi/krb5/util_cksum.c | 295 + krb5-1-7/src/lib/gssapi/krb5/util_crypt.c | 943 + krb5-1-7/src/lib/gssapi/krb5/util_seed.c | 55 + krb5-1-7/src/lib/gssapi/krb5/util_seqnum.c | 102 + krb5-1-7/src/lib/gssapi/krb5/val_cred.c | 96 + krb5-1-7/src/lib/gssapi/krb5/verify.c | 65 + .../src/lib/gssapi/krb5/wrap_size_limit.c | 183 + .../src/lib/gssapi/libgssapi_krb5.exports | 92 + krb5-1-7/src/lib/gssapi/mechglue/Makefile.in | 166 + krb5-1-7/src/lib/gssapi/mechglue/deps | 343 + .../gssapi/mechglue/g_accept_sec_context.c | 361 + .../src/lib/gssapi/mechglue/g_acquire_cred.c | 536 + .../src/lib/gssapi/mechglue/g_buffer_set.c | 57 + .../src/lib/gssapi/mechglue/g_canon_name.c | 188 + .../src/lib/gssapi/mechglue/g_compare_name.c | 210 + .../gssapi/mechglue/g_complete_auth_token.c | 70 + .../src/lib/gssapi/mechglue/g_context_time.c | 79 + .../gssapi/mechglue/g_delete_sec_context.c | 104 + krb5-1-7/src/lib/gssapi/mechglue/g_dsp_name.c | 138 + .../src/lib/gssapi/mechglue/g_dsp_status.c | 368 + krb5-1-7/src/lib/gssapi/mechglue/g_dup_name.c | 144 + .../lib/gssapi/mechglue/g_exp_sec_context.c | 139 + .../src/lib/gssapi/mechglue/g_export_name.c | 59 + krb5-1-7/src/lib/gssapi/mechglue/g_glue.c | 680 + krb5-1-7/src/lib/gssapi/mechglue/g_imp_name.c | 366 + .../lib/gssapi/mechglue/g_imp_sec_context.c | 167 + .../lib/gssapi/mechglue/g_init_sec_context.c | 252 + .../src/lib/gssapi/mechglue/g_initialize.c | 1198 ++ .../src/lib/gssapi/mechglue/g_inq_context.c | 160 + .../lib/gssapi/mechglue/g_inq_context_oid.c | 72 + krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred.c | 278 + .../src/lib/gssapi/mechglue/g_inq_cred_oid.c | 133 + .../src/lib/gssapi/mechglue/g_inq_names.c | 191 + .../src/lib/gssapi/mechglue/g_mech_invoke.c | 70 + krb5-1-7/src/lib/gssapi/mechglue/g_mechname.c | 117 + krb5-1-7/src/lib/gssapi/mechglue/g_oid_ops.c | 111 + .../lib/gssapi/mechglue/g_process_context.c | 82 + .../src/lib/gssapi/mechglue/g_rel_buffer.c | 58 + krb5-1-7/src/lib/gssapi/mechglue/g_rel_cred.c | 102 + krb5-1-7/src/lib/gssapi/mechglue/g_rel_name.c | 86 + .../src/lib/gssapi/mechglue/g_rel_oid_set.c | 43 + krb5-1-7/src/lib/gssapi/mechglue/g_seal.c | 272 + .../gssapi/mechglue/g_set_context_option.c | 110 + .../lib/gssapi/mechglue/g_set_cred_option.c | 81 + krb5-1-7/src/lib/gssapi/mechglue/g_sign.c | 135 + .../src/lib/gssapi/mechglue/g_store_cred.c | 186 + krb5-1-7/src/lib/gssapi/mechglue/g_unseal.c | 130 + .../src/lib/gssapi/mechglue/g_unwrap_aead.c | 198 + .../src/lib/gssapi/mechglue/g_unwrap_iov.c | 114 + krb5-1-7/src/lib/gssapi/mechglue/g_userok.c | 114 + krb5-1-7/src/lib/gssapi/mechglue/g_verify.c | 106 + .../src/lib/gssapi/mechglue/g_wrap_aead.c | 267 + krb5-1-7/src/lib/gssapi/mechglue/g_wrap_iov.c | 207 + .../lib/gssapi/mechglue/gssd_pname_to_uid.c | 67 + krb5-1-7/src/lib/gssapi/mechglue/mechglue.h | 42 + krb5-1-7/src/lib/gssapi/mechglue/mglueP.h | 661 + krb5-1-7/src/lib/gssapi/spnego/Makefile.in | 26 + krb5-1-7/src/lib/gssapi/spnego/deps | 17 + .../src/lib/gssapi/spnego/gssapiP_spnego.h | 427 + .../src/lib/gssapi/spnego/mech_spnego.exports | 1 + krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c | 3459 ++++ krb5-1-7/src/lib/gssapi32.def | 99 + krb5-1-7/src/lib/kadm5/Makefile.in | 107 + krb5-1-7/src/lib/kadm5/adb.h | 134 + krb5-1-7/src/lib/kadm5/admin.h | 807 + krb5-1-7/src/lib/kadm5/admin_internal.h | 80 + krb5-1-7/src/lib/kadm5/admin_xdr.h | 64 + krb5-1-7/src/lib/kadm5/alt_prof.c | 1145 ++ krb5-1-7/src/lib/kadm5/chpass_util.c | 258 + krb5-1-7/src/lib/kadm5/chpass_util_strings.et | 58 + krb5-1-7/src/lib/kadm5/clnt/Makefile.in | 77 + krb5-1-7/src/lib/kadm5/clnt/client_handle.c | 9 + krb5-1-7/src/lib/kadm5/clnt/client_init.c | 849 + krb5-1-7/src/lib/kadm5/clnt/client_internal.h | 97 + .../src/lib/kadm5/clnt/client_principal.c | 547 + krb5-1-7/src/lib/kadm5/clnt/client_rpc.c | 327 + .../src/lib/kadm5/clnt/clnt_chpass_util.c | 16 + krb5-1-7/src/lib/kadm5/clnt/clnt_policy.c | 152 + krb5-1-7/src/lib/kadm5/clnt/clnt_privs.c | 30 + krb5-1-7/src/lib/kadm5/clnt/deps | 82 + .../src/lib/kadm5/clnt/libkadm5clnt.exports | 132 + krb5-1-7/src/lib/kadm5/deps | 101 + krb5-1-7/src/lib/kadm5/kadm_err.et | 63 + krb5-1-7/src/lib/kadm5/kadm_rpc.h | 305 + krb5-1-7/src/lib/kadm5/kadm_rpc_xdr.c | 1067 ++ krb5-1-7/src/lib/kadm5/logger.c | 971 ++ krb5-1-7/src/lib/kadm5/misc_free.c | 115 + krb5-1-7/src/lib/kadm5/ovsec_glue.c | 194 + krb5-1-7/src/lib/kadm5/server_internal.h | 142 + krb5-1-7/src/lib/kadm5/srv/Makefile.in | 94 + krb5-1-7/src/lib/kadm5/srv/adb_xdr.c | 110 + krb5-1-7/src/lib/kadm5/srv/deps | 159 + .../src/lib/kadm5/srv/libkadm5srv.exports | 168 + krb5-1-7/src/lib/kadm5/srv/server_acl.c | 833 + krb5-1-7/src/lib/kadm5/srv/server_acl.h | 109 + krb5-1-7/src/lib/kadm5/srv/server_dict.c | 207 + krb5-1-7/src/lib/kadm5/srv/server_handle.c | 9 + krb5-1-7/src/lib/kadm5/srv/server_init.c | 470 + krb5-1-7/src/lib/kadm5/srv/server_kdb.c | 447 + krb5-1-7/src/lib/kadm5/srv/server_misc.c | 183 + krb5-1-7/src/lib/kadm5/srv/svr_chpass_util.c | 16 + krb5-1-7/src/lib/kadm5/srv/svr_iters.c | 274 + krb5-1-7/src/lib/kadm5/srv/svr_misc_free.c | 37 + krb5-1-7/src/lib/kadm5/srv/svr_policy.c | 314 + krb5-1-7/src/lib/kadm5/srv/svr_principal.c | 2315 +++ krb5-1-7/src/lib/kadm5/str_conv.c | 404 + krb5-1-7/src/lib/kadm5/unit-test/Makefile.in | 145 + .../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 | 956 ++ .../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 | 1943 +++ .../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 | 956 ++ .../kadm5/unit-test/api.2/crte-principal.exp | 1340 ++ .../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 | 515 + .../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 | 1943 +++ .../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 | 220 + krb5-1-7/src/lib/kadm5/unit-test/deps | 82 + .../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-7/src/lib/kadm5/unit-test/init-test.c | 30 + krb5-1-7/src/lib/kadm5/unit-test/iter-test.c | 48 + krb5-1-7/src/lib/kadm5/unit-test/lib/lib.t | 305 + krb5-1-7/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-7/src/lib/kadm5/unit-test/site.exp | 2 + krb5-1-7/src/lib/kdb/Makefile.in | 66 + krb5-1-7/src/lib/kdb/adb_err.et | 16 + krb5-1-7/src/lib/kdb/decrypt_key.c | 139 + krb5-1-7/src/lib/kdb/deps | 119 + krb5-1-7/src/lib/kdb/encrypt_key.c | 136 + krb5-1-7/src/lib/kdb/iprop.x | 223 + krb5-1-7/src/lib/kdb/iprop_xdr.c | 351 + krb5-1-7/src/lib/kdb/kdb5.c | 3117 ++++ krb5-1-7/src/lib/kdb/kdb5.h | 36 + krb5-1-7/src/lib/kdb/kdb5int.h | 44 + krb5-1-7/src/lib/kdb/kdb_convert.c | 1006 ++ krb5-1-7/src/lib/kdb/kdb_cpw.c | 636 + krb5-1-7/src/lib/kdb/kdb_default.c | 680 + krb5-1-7/src/lib/kdb/kdb_log.c | 935 + krb5-1-7/src/lib/kdb/keytab.c | 242 + krb5-1-7/src/lib/kdb/libkdb5.exports | 85 + krb5-1-7/src/lib/krb4_32.def | 86 + krb5-1-7/src/lib/krb5.rc | 44 + krb5-1-7/src/lib/krb5/Makefile.in | 138 + krb5-1-7/src/lib/krb5/asn.1/KRB5-asn.py | 436 + krb5-1-7/src/lib/krb5/asn.1/Makefile.in | 59 + krb5-1-7/src/lib/krb5/asn.1/TODO.asn1 | 90 + krb5-1-7/src/lib/krb5/asn.1/asn1_decode.c | 277 + krb5-1-7/src/lib/krb5/asn.1/asn1_decode.h | 96 + krb5-1-7/src/lib/krb5/asn.1/asn1_encode.c | 700 + krb5-1-7/src/lib/krb5/asn.1/asn1_encode.h | 664 + krb5-1-7/src/lib/krb5/asn.1/asn1_get.c | 119 + krb5-1-7/src/lib/krb5/asn.1/asn1_get.h | 85 + krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.c | 2359 +++ krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.h | 281 + krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.c | 1852 ++ krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.h | 136 + krb5-1-7/src/lib/krb5/asn.1/asn1_make.c | 161 + krb5-1-7/src/lib/krb5/asn.1/asn1_make.h | 135 + krb5-1-7/src/lib/krb5/asn.1/asn1_misc.c | 38 + krb5-1-7/src/lib/krb5/asn.1/asn1_misc.h | 40 + krb5-1-7/src/lib/krb5/asn.1/asn1buf.c | 384 + krb5-1-7/src/lib/krb5/asn.1/asn1buf.h | 218 + krb5-1-7/src/lib/krb5/asn.1/asn1glue.h | 47 + krb5-1-7/src/lib/krb5/asn.1/deps | 125 + krb5-1-7/src/lib/krb5/asn.1/krb5_decode.c | 1330 ++ krb5-1-7/src/lib/krb5/asn.1/krb5_encode.c | 174 + krb5-1-7/src/lib/krb5/asn.1/krbasn1.h | 76 + krb5-1-7/src/lib/krb5/asn.1/ldap_key_seq.c | 386 + krb5-1-7/src/lib/krb5/ccache/Makefile.in | 115 + krb5-1-7/src/lib/krb5/ccache/cc-int.h | 116 + krb5-1-7/src/lib/krb5/ccache/cc_file.c | 2639 +++ krb5-1-7/src/lib/krb5/ccache/cc_keyring.c | 2111 +++ krb5-1-7/src/lib/krb5/ccache/cc_memory.c | 823 + krb5-1-7/src/lib/krb5/ccache/cc_mslsa.c | 2762 +++ krb5-1-7/src/lib/krb5/ccache/cc_retr.c | 382 + .../src/lib/krb5/ccache/ccapi/Makefile.in | 26 + krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.c | 1699 ++ krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.h | 176 + .../src/lib/krb5/ccache/ccapi/stdcc_util.c | 1068 ++ .../src/lib/krb5/ccache/ccapi/stdcc_util.h | 48 + krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.c | 100 + krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.h | 203 + krb5-1-7/src/lib/krb5/ccache/ccbase.c | 619 + krb5-1-7/src/lib/krb5/ccache/cccopy.c | 62 + krb5-1-7/src/lib/krb5/ccache/cccursor.c | 366 + krb5-1-7/src/lib/krb5/ccache/ccdefault.c | 144 + krb5-1-7/src/lib/krb5/ccache/ccdefops.c | 59 + krb5-1-7/src/lib/krb5/ccache/ccfns.c | 193 + krb5-1-7/src/lib/krb5/ccache/deps | 126 + krb5-1-7/src/lib/krb5/ccache/fcc.h | 36 + krb5-1-7/src/lib/krb5/ccache/scc.h | 101 + krb5-1-7/src/lib/krb5/ccache/ser_cc.c | 202 + krb5-1-7/src/lib/krb5/ccache/t_cc.c | 412 + krb5-1-7/src/lib/krb5/ccache/t_cccursor.c | 265 + krb5-1-7/src/lib/krb5/ccache/t_memory.c | 140 + krb5-1-7/src/lib/krb5/ccache/t_stdio.c | 169 + krb5-1-7/src/lib/krb5/deps | 15 + .../src/lib/krb5/error_tables/Makefile.in | 60 + .../src/lib/krb5/error_tables/asn1_err.et | 15 + krb5-1-7/src/lib/krb5/error_tables/deps | 13 + krb5-1-7/src/lib/krb5/error_tables/init_ets.c | 50 + .../src/lib/krb5/error_tables/kdb5_err.et | 86 + .../src/lib/krb5/error_tables/krb524_err.et | 34 + .../src/lib/krb5/error_tables/krb5_err.et | 354 + .../src/lib/krb5/error_tables/kv5m_err.et | 92 + krb5-1-7/src/lib/krb5/keytab/Makefile.in | 80 + krb5-1-7/src/lib/krb5/keytab/deps | 113 + krb5-1-7/src/lib/krb5/keytab/kt-int.h | 42 + krb5-1-7/src/lib/krb5/keytab/kt_file.c | 1765 ++ krb5-1-7/src/lib/krb5/keytab/kt_memory.c | 669 + krb5-1-7/src/lib/krb5/keytab/kt_srvtab.c | 468 + krb5-1-7/src/lib/krb5/keytab/ktadd.c | 43 + krb5-1-7/src/lib/krb5/keytab/ktbase.c | 297 + krb5-1-7/src/lib/krb5/keytab/ktdefault.c | 46 + krb5-1-7/src/lib/krb5/keytab/ktfns.c | 100 + krb5-1-7/src/lib/krb5/keytab/ktfr_entry.c | 53 + krb5-1-7/src/lib/krb5/keytab/ktremove.c | 42 + krb5-1-7/src/lib/krb5/keytab/read_servi.c | 84 + krb5-1-7/src/lib/krb5/keytab/t_keytab.c | 466 + krb5-1-7/src/lib/krb5/krb/Makefile.in | 395 + krb5-1-7/src/lib/krb5/krb/addr_comp.c | 48 + krb5-1-7/src/lib/krb5/krb/addr_order.c | 63 + krb5-1-7/src/lib/krb5/krb/addr_srch.c | 68 + krb5-1-7/src/lib/krb5/krb/appdefault.c | 166 + krb5-1-7/src/lib/krb5/krb/auth_con.c | 570 + krb5-1-7/src/lib/krb5/krb/auth_con.h | 37 + krb5-1-7/src/lib/krb5/krb/bld_pr_ext.c | 95 + krb5-1-7/src/lib/krb5/krb/bld_princ.c | 188 + krb5-1-7/src/lib/krb5/krb/brand.c | 72 + krb5-1-7/src/lib/krb5/krb/chk_trans.c | 434 + krb5-1-7/src/lib/krb5/krb/chpw.c | 539 + krb5-1-7/src/lib/krb5/krb/cleanup.h | 29 + krb5-1-7/src/lib/krb5/krb/conv_creds.c | 60 + krb5-1-7/src/lib/krb5/krb/conv_princ.c | 353 + krb5-1-7/src/lib/krb5/krb/copy_addrs.c | 139 + krb5-1-7/src/lib/krb5/krb/copy_athctr.c | 83 + krb5-1-7/src/lib/krb5/krb/copy_auth.c | 278 + krb5-1-7/src/lib/krb5/krb/copy_cksum.c | 51 + krb5-1-7/src/lib/krb5/krb/copy_creds.c | 116 + krb5-1-7/src/lib/krb5/krb/copy_data.c | 96 + krb5-1-7/src/lib/krb5/krb/copy_key.c | 51 + krb5-1-7/src/lib/krb5/krb/copy_princ.c | 79 + krb5-1-7/src/lib/krb5/krb/copy_tick.c | 126 + krb5-1-7/src/lib/krb5/krb/cp_key_cnt.c | 47 + krb5-1-7/src/lib/krb5/krb/decode_kdc.c | 70 + krb5-1-7/src/lib/krb5/krb/decrypt_tk.c | 73 + krb5-1-7/src/lib/krb5/krb/deltat.c | 1455 ++ krb5-1-7/src/lib/krb5/krb/deps | 945 + krb5-1-7/src/lib/krb5/krb/enc_helper.c | 50 + krb5-1-7/src/lib/krb5/krb/encode_kdc.c | 128 + krb5-1-7/src/lib/krb5/krb/encrypt_tk.c | 67 + krb5-1-7/src/lib/krb5/krb/fast.c | 524 + krb5-1-7/src/lib/krb5/krb/fast.h | 82 + krb5-1-7/src/lib/krb5/krb/free_rtree.c | 43 + krb5-1-7/src/lib/krb5/krb/fwd_tgt.c | 197 + krb5-1-7/src/lib/krb5/krb/gc_frm_kdc.c | 1361 ++ krb5-1-7/src/lib/krb5/krb/gc_via_tkt.c | 377 + krb5-1-7/src/lib/krb5/krb/gen_seqnum.c | 76 + krb5-1-7/src/lib/krb5/krb/gen_subkey.c | 70 + krb5-1-7/src/lib/krb5/krb/get_creds.c | 339 + krb5-1-7/src/lib/krb5/krb/get_in_tkt.c | 1558 ++ krb5-1-7/src/lib/krb5/krb/gic_keytab.c | 222 + krb5-1-7/src/lib/krb5/krb/gic_opt.c | 487 + krb5-1-7/src/lib/krb5/krb/gic_pwd.c | 532 + krb5-1-7/src/lib/krb5/krb/in_tkt_sky.c | 107 + krb5-1-7/src/lib/krb5/krb/init_ctx.c | 617 + krb5-1-7/src/lib/krb5/krb/init_keyblock.c | 41 + krb5-1-7/src/lib/krb5/krb/int-proto.h | 69 + krb5-1-7/src/lib/krb5/krb/kdc_rep_dc.c | 80 + krb5-1-7/src/lib/krb5/krb/kerrs.c | 149 + krb5-1-7/src/lib/krb5/krb/kfree.c | 861 + krb5-1-7/src/lib/krb5/krb/mk_cred.c | 315 + krb5-1-7/src/lib/krb5/krb/mk_error.c | 52 + krb5-1-7/src/lib/krb5/krb/mk_priv.c | 235 + krb5-1-7/src/lib/krb5/krb/mk_rep.c | 150 + krb5-1-7/src/lib/krb5/krb/mk_req.c | 91 + krb5-1-7/src/lib/krb5/krb/mk_req_ext.c | 418 + krb5-1-7/src/lib/krb5/krb/mk_safe.c | 261 + krb5-1-7/src/lib/krb5/krb/pac.c | 872 + krb5-1-7/src/lib/krb5/krb/parse.c | 340 + krb5-1-7/src/lib/krb5/krb/pkinit_apple_asn1.c | 956 ++ .../lib/krb5/krb/pkinit_apple_cert_store.c | 625 + .../src/lib/krb5/krb/pkinit_apple_client.c | 263 + krb5-1-7/src/lib/krb5/krb/pkinit_apple_cms.c | 559 + .../src/lib/krb5/krb/pkinit_apple_utils.c | 433 + krb5-1-7/src/lib/krb5/krb/pr_to_salt.c | 86 + krb5-1-7/src/lib/krb5/krb/preauth.c | 574 + krb5-1-7/src/lib/krb5/krb/preauth2.c | 2074 +++ krb5-1-7/src/lib/krb5/krb/princ_comp.c | 179 + krb5-1-7/src/lib/krb5/krb/rd_cred.c | 245 + krb5-1-7/src/lib/krb5/krb/rd_error.c | 50 + krb5-1-7/src/lib/krb5/krb/rd_priv.c | 275 + krb5-1-7/src/lib/krb5/krb/rd_rep.c | 202 + krb5-1-7/src/lib/krb5/krb/rd_req.c | 108 + krb5-1-7/src/lib/krb5/krb/rd_req_dec.c | 717 + krb5-1-7/src/lib/krb5/krb/rd_safe.c | 279 + krb5-1-7/src/lib/krb5/krb/recvauth.c | 266 + krb5-1-7/src/lib/krb5/krb/send_tgs.c | 345 + krb5-1-7/src/lib/krb5/krb/sendauth.c | 236 + krb5-1-7/src/lib/krb5/krb/ser_actx.c | 564 + krb5-1-7/src/lib/krb5/krb/ser_adata.c | 198 + krb5-1-7/src/lib/krb5/krb/ser_addr.c | 202 + krb5-1-7/src/lib/krb5/krb/ser_auth.c | 349 + krb5-1-7/src/lib/krb5/krb/ser_cksum.c | 200 + krb5-1-7/src/lib/krb5/krb/ser_ctx.c | 621 + krb5-1-7/src/lib/krb5/krb/ser_eblk.c | 256 + krb5-1-7/src/lib/krb5/krb/ser_key.c | 198 + krb5-1-7/src/lib/krb5/krb/ser_princ.c | 181 + krb5-1-7/src/lib/krb5/krb/serialize.c | 273 + krb5-1-7/src/lib/krb5/krb/set_realm.c | 51 + krb5-1-7/src/lib/krb5/krb/srv_dec_tkt.c | 97 + krb5-1-7/src/lib/krb5/krb/srv_rcache.c | 92 + krb5-1-7/src/lib/krb5/krb/str_conv.c | 388 + krb5-1-7/src/lib/krb5/krb/strftime.c | 415 + krb5-1-7/src/lib/krb5/krb/strptime.c | 386 + krb5-1-7/src/lib/krb5/krb/t_ad_fx_armor.c | 36 + krb5-1-7/src/lib/krb5/krb/t_authdata.c | 103 + krb5-1-7/src/lib/krb5/krb/t_deltat.c | 158 + krb5-1-7/src/lib/krb5/krb/t_expand.c | 2 + krb5-1-7/src/lib/krb5/krb/t_kerb.c | 227 + krb5-1-7/src/lib/krb5/krb/t_krb5.conf | 52 + krb5-1-7/src/lib/krb5/krb/t_pac.c | 322 + krb5-1-7/src/lib/krb5/krb/t_princ.c | 403 + krb5-1-7/src/lib/krb5/krb/t_ref_kerb.out | 19 + krb5-1-7/src/lib/krb5/krb/t_ser.c | 727 + krb5-1-7/src/lib/krb5/krb/t_walk_rtree.c | 58 + krb5-1-7/src/lib/krb5/krb/tgtname.c | 42 + krb5-1-7/src/lib/krb5/krb/transit-tests | 54 + krb5-1-7/src/lib/krb5/krb/unparse.c | 269 + krb5-1-7/src/lib/krb5/krb/valid_times.c | 62 + krb5-1-7/src/lib/krb5/krb/vfy_increds.c | 232 + krb5-1-7/src/lib/krb5/krb/vic_opt.c | 14 + krb5-1-7/src/lib/krb5/krb/walk_rtree.c | 580 + krb5-1-7/src/lib/krb5/krb/walktree-tests | 79 + krb5-1-7/src/lib/krb5/krb/x-deltat.y | 229 + krb5-1-7/src/lib/krb5/krb5_libinit.c | 109 + krb5-1-7/src/lib/krb5/krb5_libinit.h | 9 + krb5-1-7/src/lib/krb5/libkrb5.exports | 585 + krb5-1-7/src/lib/krb5/os/Makefile.in | 240 + krb5-1-7/src/lib/krb5/os/accessor.c | 152 + krb5-1-7/src/lib/krb5/os/an_to_ln.c | 828 + krb5-1-7/src/lib/krb5/os/c_ustime.c | 118 + krb5-1-7/src/lib/krb5/os/ccdefname.c | 324 + krb5-1-7/src/lib/krb5/os/changepw.c | 411 + krb5-1-7/src/lib/krb5/os/def_realm.c | 247 + krb5-1-7/src/lib/krb5/os/deps | 463 + krb5-1-7/src/lib/krb5/os/dnsglue.c | 335 + krb5-1-7/src/lib/krb5/os/dnsglue.h | 157 + krb5-1-7/src/lib/krb5/os/dnssrv.c | 184 + krb5-1-7/src/lib/krb5/os/free_hstrl.c | 42 + krb5-1-7/src/lib/krb5/os/free_krbhs.c | 47 + krb5-1-7/src/lib/krb5/os/full_ipadr.c | 86 + krb5-1-7/src/lib/krb5/os/gen_port.c | 49 + krb5-1-7/src/lib/krb5/os/gen_rname.c | 52 + krb5-1-7/src/lib/krb5/os/genaddrs.c | 130 + krb5-1-7/src/lib/krb5/os/get_krbhst.c | 128 + krb5-1-7/src/lib/krb5/os/hostaddr.c | 137 + krb5-1-7/src/lib/krb5/os/hst_realm.c | 565 + krb5-1-7/src/lib/krb5/os/init_os_ctx.c | 505 + krb5-1-7/src/lib/krb5/os/krbfileio.c | 103 + krb5-1-7/src/lib/krb5/os/ktdefname.c | 80 + krb5-1-7/src/lib/krb5/os/kuserok.c | 172 + krb5-1-7/src/lib/krb5/os/localaddr.c | 1576 ++ krb5-1-7/src/lib/krb5/os/locate_kdc.c | 867 + krb5-1-7/src/lib/krb5/os/lock_file.c | 139 + krb5-1-7/src/lib/krb5/os/mk_faddr.c | 84 + krb5-1-7/src/lib/krb5/os/net_read.c | 65 + krb5-1-7/src/lib/krb5/os/net_write.c | 82 + krb5-1-7/src/lib/krb5/os/os-proto.h | 77 + krb5-1-7/src/lib/krb5/os/osconfig.c | 46 + krb5-1-7/src/lib/krb5/os/port2ip.c | 84 + krb5-1-7/src/lib/krb5/os/prompter.c | 328 + krb5-1-7/src/lib/krb5/os/promptusr.c | 161 + krb5-1-7/src/lib/krb5/os/read_msg.c | 66 + krb5-1-7/src/lib/krb5/os/read_pwd.c | 297 + krb5-1-7/src/lib/krb5/os/realm_dom.c | 65 + krb5-1-7/src/lib/krb5/os/realm_iter.c | 60 + krb5-1-7/src/lib/krb5/os/ref_std_conf.out | 13 + krb5-1-7/src/lib/krb5/os/sendto_kdc.c | 1348 ++ krb5-1-7/src/lib/krb5/os/sn2princ.c | 216 + krb5-1-7/src/lib/krb5/os/t_an_to_ln.c | 41 + krb5-1-7/src/lib/krb5/os/t_gifconf.c | 134 + krb5-1-7/src/lib/krb5/os/t_locate_kdc.c | 132 + krb5-1-7/src/lib/krb5/os/t_realm_iter.c | 44 + krb5-1-7/src/lib/krb5/os/t_std_conf.c | 247 + krb5-1-7/src/lib/krb5/os/td_krb5.conf | 19 + krb5-1-7/src/lib/krb5/os/thread_safe.c | 40 + krb5-1-7/src/lib/krb5/os/timeofday.c | 56 + krb5-1-7/src/lib/krb5/os/toffset.c | 120 + krb5-1-7/src/lib/krb5/os/unlck_file.c | 37 + krb5-1-7/src/lib/krb5/os/ustime.c | 66 + krb5-1-7/src/lib/krb5/os/write_msg.c | 76 + krb5-1-7/src/lib/krb5/posix/Makefile.in | 18 + krb5-1-7/src/lib/krb5/posix/syslog.c | 10 + krb5-1-7/src/lib/krb5/rcache/Makefile.in | 55 + krb5-1-7/src/lib/krb5/rcache/README | 82 + krb5-1-7/src/lib/krb5/rcache/RELEASE | 17 + krb5-1-7/src/lib/krb5/rcache/deps | 93 + krb5-1-7/src/lib/krb5/rcache/rc-int.h | 78 + krb5-1-7/src/lib/krb5/rcache/rc_base.c | 175 + krb5-1-7/src/lib/krb5/rcache/rc_base.h | 16 + krb5-1-7/src/lib/krb5/rcache/rc_conv.c | 79 + krb5-1-7/src/lib/krb5/rcache/rc_dfl.c | 874 + krb5-1-7/src/lib/krb5/rcache/rc_dfl.h | 56 + krb5-1-7/src/lib/krb5/rcache/rc_io.c | 535 + krb5-1-7/src/lib/krb5/rcache/rc_io.h | 71 + krb5-1-7/src/lib/krb5/rcache/rc_none.c | 95 + krb5-1-7/src/lib/krb5/rcache/rcdef.c | 49 + krb5-1-7/src/lib/krb5/rcache/rcfns.c | 96 + krb5-1-7/src/lib/krb5/rcache/ser_rc.c | 209 + krb5-1-7/src/lib/krb5/rcache/t_replay.c | 268 + .../krb5/unicode/CompositionExclusions.txt | 176 + krb5-1-7/src/lib/krb5/unicode/Makefile.in | 69 + krb5-1-7/src/lib/krb5/unicode/UCD-Terms | 29 + krb5-1-7/src/lib/krb5/unicode/UnicodeData.txt | 13874 +++++++++++++++ krb5-1-7/src/lib/krb5/unicode/deps | 14 + .../lib/krb5/unicode/ucdata/MUTTUCData.txt | 303 + krb5-1-7/src/lib/krb5/unicode/ucdata/README | 313 + krb5-1-7/src/lib/krb5/unicode/ucdata/api.txt | 401 + .../src/lib/krb5/unicode/ucdata/bidiapi.txt | 84 + .../src/lib/krb5/unicode/ucdata/format.txt | 267 + krb5-1-7/src/lib/krb5/unicode/ucdata/ucdata.c | 1494 ++ krb5-1-7/src/lib/krb5/unicode/ucdata/ucdata.h | 351 + .../src/lib/krb5/unicode/ucdata/ucdata.man | 504 + .../src/lib/krb5/unicode/ucdata/ucgendat.c | 1942 +++ krb5-1-7/src/lib/krb5/unicode/ucdata/ucpgba.c | 752 + krb5-1-7/src/lib/krb5/unicode/ucdata/ucpgba.h | 163 + .../src/lib/krb5/unicode/ucdata/ucpgba.man | 97 + .../src/lib/krb5/unicode/ucdata/uctable.h | 14306 ++++++++++++++++ krb5-1-7/src/lib/krb5/unicode/ucstr.c | 452 + krb5-1-7/src/lib/krb5/unicode/ure/README | 212 + krb5-1-7/src/lib/krb5/unicode/ure/ure.c | 2131 +++ krb5-1-7/src/lib/krb5/unicode/ure/ure.h | 149 + krb5-1-7/src/lib/krb5/unicode/ure/urestubs.c | 126 + krb5-1-7/src/lib/krb5/unicode/utbm/README | 121 + krb5-1-7/src/lib/krb5/unicode/utbm/utbm.c | 472 + krb5-1-7/src/lib/krb5/unicode/utbm/utbm.h | 107 + krb5-1-7/src/lib/krb5/unicode/utbm/utbmstub.c | 105 + krb5-1-7/src/lib/krb5_32.def | 302 + krb5-1-7/src/lib/rpc/Makefile.in | 241 + krb5-1-7/src/lib/rpc/auth_gss.c | 633 + krb5-1-7/src/lib/rpc/auth_gssapi.c | 822 + krb5-1-7/src/lib/rpc/auth_gssapi_misc.c | 334 + krb5-1-7/src/lib/rpc/auth_none.c | 145 + krb5-1-7/src/lib/rpc/auth_unix.c | 328 + krb5-1-7/src/lib/rpc/authgss_prot.c | 366 + krb5-1-7/src/lib/rpc/authunix_prot.c | 64 + krb5-1-7/src/lib/rpc/bindresvport.c | 83 + krb5-1-7/src/lib/rpc/clnt_generic.c | 115 + krb5-1-7/src/lib/rpc/clnt_perror.c | 350 + krb5-1-7/src/lib/rpc/clnt_raw.c | 268 + krb5-1-7/src/lib/rpc/clnt_simple.c | 132 + krb5-1-7/src/lib/rpc/clnt_tcp.c | 495 + krb5-1-7/src/lib/rpc/clnt_udp.c | 483 + krb5-1-7/src/lib/rpc/deps | 323 + krb5-1-7/src/lib/rpc/dyn.c | 555 + krb5-1-7/src/lib/rpc/dyn.h | 79 + krb5-1-7/src/lib/rpc/dynP.h | 50 + krb5-1-7/src/lib/rpc/dyntest.c | 216 + krb5-1-7/src/lib/rpc/get_myaddress.c | 117 + krb5-1-7/src/lib/rpc/getrpcent.c | 241 + krb5-1-7/src/lib/rpc/getrpcport.c | 66 + krb5-1-7/src/lib/rpc/gssrpcint.h | 39 + krb5-1-7/src/lib/rpc/libgssrpc.exports | 142 + krb5-1-7/src/lib/rpc/pmap_clnt.c | 167 + krb5-1-7/src/lib/rpc/pmap_getmaps.c | 87 + krb5-1-7/src/lib/rpc/pmap_getport.c | 92 + krb5-1-7/src/lib/rpc/pmap_prot.c | 55 + krb5-1-7/src/lib/rpc/pmap_prot2.c | 114 + krb5-1-7/src/lib/rpc/pmap_rmt.c | 420 + krb5-1-7/src/lib/rpc/rpc_callmsg.c | 194 + krb5-1-7/src/lib/rpc/rpc_commondata.c | 47 + krb5-1-7/src/lib/rpc/rpc_dtablesize.c | 62 + krb5-1-7/src/lib/rpc/rpc_prot.c | 293 + krb5-1-7/src/lib/rpc/svc.c | 534 + krb5-1-7/src/lib/rpc/svc_auth.c | 109 + krb5-1-7/src/lib/rpc/svc_auth_gss.c | 707 + krb5-1-7/src/lib/rpc/svc_auth_gssapi.c | 1119 ++ krb5-1-7/src/lib/rpc/svc_auth_none.c | 75 + krb5-1-7/src/lib/rpc/svc_auth_unix.c | 141 + krb5-1-7/src/lib/rpc/svc_raw.c | 160 + krb5-1-7/src/lib/rpc/svc_run.c | 74 + krb5-1-7/src/lib/rpc/svc_simple.c | 149 + krb5-1-7/src/lib/rpc/svc_tcp.c | 533 + krb5-1-7/src/lib/rpc/svc_udp.c | 534 + krb5-1-7/src/lib/rpc/unit-test/Makefile.in | 71 + krb5-1-7/src/lib/rpc/unit-test/client.c | 276 + .../src/lib/rpc/unit-test/config/unix.exp | 185 + krb5-1-7/src/lib/rpc/unit-test/deps | 35 + .../src/lib/rpc/unit-test/lib/helpers.exp | 236 + .../lib/rpc/unit-test/rpc_test.0/expire.exp | 48 + .../lib/rpc/unit-test/rpc_test.0/fullrun.exp | 91 + .../lib/rpc/unit-test/rpc_test.0/gsserr.exp | 30 + krb5-1-7/src/lib/rpc/unit-test/rpc_test.h | 13 + krb5-1-7/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-7/src/lib/rpc/unit-test/rpc_test_svc.c | 74 + krb5-1-7/src/lib/rpc/unit-test/server.c | 262 + krb5-1-7/src/lib/rpc/xdr.c | 675 + krb5-1-7/src/lib/rpc/xdr_alloc.c | 151 + krb5-1-7/src/lib/rpc/xdr_array.c | 158 + krb5-1-7/src/lib/rpc/xdr_float.c | 289 + krb5-1-7/src/lib/rpc/xdr_mem.c | 182 + krb5-1-7/src/lib/rpc/xdr_rec.c | 570 + krb5-1-7/src/lib/rpc/xdr_reference.c | 137 + krb5-1-7/src/lib/rpc/xdr_sizeof.c | 163 + krb5-1-7/src/lib/rpc/xdr_stdio.c | 170 + krb5-1-7/src/lib/win_glue.c | 489 + krb5-1-7/src/lib/xpprof32.def | 28 + krb5-1-7/src/patchlevel.h | 58 + .../src/plugins/authdata/greet/Makefile.in | 39 + krb5-1-7/src/plugins/authdata/greet/deps | 6 + .../src/plugins/authdata/greet/greet.exports | 1 + .../src/plugins/authdata/greet/greet_auth.c | 97 + krb5-1-7/src/plugins/kdb/db2/Makefile.in | 95 + krb5-1-7/src/plugins/kdb/db2/adb_openclose.c | 416 + krb5-1-7/src/plugins/kdb/db2/adb_policy.c | 390 + krb5-1-7/src/plugins/kdb/db2/db2.exports | 1 + krb5-1-7/src/plugins/kdb/db2/db2_exp.c | 260 + krb5-1-7/src/plugins/kdb/db2/deps | 70 + krb5-1-7/src/plugins/kdb/db2/kdb_db2.c | 1841 ++ krb5-1-7/src/plugins/kdb/db2/kdb_db2.h | 222 + krb5-1-7/src/plugins/kdb/db2/kdb_xdr.c | 493 + krb5-1-7/src/plugins/kdb/db2/kdb_xdr.h | 34 + .../src/plugins/kdb/db2/libdb2/CHANGELOG.db2 | 123 + .../src/plugins/kdb/db2/libdb2/Makefile.in | 38 + .../src/plugins/kdb/db2/libdb2/Makefile.inc | 10 + krb5-1-7/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 | 17 + .../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 | 378 + .../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 | 480 + .../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/deps | 69 + .../src/plugins/kdb/db2/libdb2/btree/extern.h | 110 + .../src/plugins/kdb/db2/libdb2/db/Makefile.in | 14 + .../plugins/kdb/db2/libdb2/db/Makefile.inc | 5 + krb5-1-7/src/plugins/kdb/db2/libdb2/db/db.c | 99 + krb5-1-7/src/plugins/kdb/db2/libdb2/db/deps | 7 + krb5-1-7/src/plugins/kdb/db2/libdb2/deps | 1 + .../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 | 16 + .../plugins/kdb/db2/libdb2/hash/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/hash/dbm.c | 359 + krb5-1-7/src/plugins/kdb/db2/libdb2/hash/deps | 44 + .../src/plugins/kdb/db2/libdb2/hash/extern.h | 109 + .../src/plugins/kdb/db2/libdb2/hash/hash.c | 1070 ++ .../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 + .../plugins/kdb/db2/libdb2/include/config.h | 23 + .../kdb/db2/libdb2/include/db-config.h | 17 + .../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 | 14 + .../plugins/kdb/db2/libdb2/mpool/Makefile.inc | 5 + .../src/plugins/kdb/db2/libdb2/mpool/README | 7 + .../src/plugins/kdb/db2/libdb2/mpool/deps | 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 | 16 + .../plugins/kdb/db2/libdb2/recno/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/recno/deps | 51 + .../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 | 248 + .../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 | 754 + krb5-1-7/src/plugins/kdb/db2/libdb2/test/deps | 1 + .../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 | 904 + krb5-1-7/src/plugins/kdb/db2/pol_xdr.c | 90 + krb5-1-7/src/plugins/kdb/db2/policy_db.h | 101 + krb5-1-7/src/plugins/kdb/ldap/Makefile.in | 47 + krb5-1-7/src/plugins/kdb/ldap/deps | 18 + krb5-1-7/src/plugins/kdb/ldap/kldap.exports | 1 + krb5-1-7/src/plugins/kdb/ldap/ldap_exp.c | 92 + .../plugins/kdb/ldap/ldap_util/Makefile.in | 29 + krb5-1-7/src/plugins/kdb/ldap/ldap_util/deps | 1 + .../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 | 880 + .../kdb/ldap/ldap_util/kdb5_ldap_policy.h | 37 + .../kdb/ldap/ldap_util/kdb5_ldap_realm.c | 2681 +++ .../kdb/ldap/ldap_util/kdb5_ldap_realm.h | 61 + .../kdb/ldap/ldap_util/kdb5_ldap_services.c | 2162 +++ .../kdb/ldap/ldap_util/kdb5_ldap_services.h | 69 + .../kdb/ldap/ldap_util/kdb5_ldap_util.M | 938 + .../kdb/ldap/ldap_util/kdb5_ldap_util.c | 648 + .../kdb/ldap/ldap_util/kdb5_ldap_util.h | 80 + .../plugins/kdb/ldap/libkdb_ldap/Makefile.in | 86 + .../src/plugins/kdb/ldap/libkdb_ldap/deps | 271 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c | 491 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h | 331 + .../kdb/ldap/libkdb_ldap/kdb_ldap_conn.c | 354 + .../plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c | 228 + .../plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h | 34 + .../kdb/ldap/libkdb_ldap/kerberos.ldif | 787 + .../kdb/ldap/libkdb_ldap/kerberos.schema | 638 + .../kdb/ldap/libkdb_ldap/ldap_create.c | 386 + .../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 | 142 + .../kdb/ldap/libkdb_ldap/ldap_handle.c | 278 + .../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 | 2271 +++ .../plugins/kdb/ldap/libkdb_ldap/ldap_misc.h | 155 + .../kdb/ldap/libkdb_ldap/ldap_principal.c | 441 + .../kdb/ldap/libkdb_ldap/ldap_principal.h | 122 + .../kdb/ldap/libkdb_ldap/ldap_principal2.c | 1354 ++ .../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 | 1491 ++ .../plugins/kdb/ldap/libkdb_ldap/ldap_realm.h | 100 + .../ldap/libkdb_ldap/ldap_service_rights.c | 769 + .../kdb/ldap/libkdb_ldap/ldap_service_stash.c | 281 + .../kdb/ldap/libkdb_ldap/ldap_service_stash.h | 55 + .../kdb/ldap/libkdb_ldap/ldap_services.c | 598 + .../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 | 53 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.c | 232 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.h | 61 + .../src/plugins/locate/python/Makefile.in | 30 + krb5-1-7/src/plugins/locate/python/deps | 9 + .../plugins/locate/python/locate-service.py | 77 + .../src/plugins/locate/python/py-locate.c | 322 + .../src/plugins/locate/python/python.exports | 1 + .../plugins/preauth/cksum_body/Makefile.in | 41 + .../preauth/cksum_body/cksum_body.exports | 2 + .../preauth/cksum_body/cksum_body_main.c | 667 + krb5-1-7/src/plugins/preauth/cksum_body/deps | 7 + .../preauth/encrypted_challenge/Makefile.in | 41 + .../plugins/preauth/encrypted_challenge/deps | 14 + .../encrypted_challenge.exports | 2 + .../encrypted_challenge_main.c | 408 + krb5-1-7/src/plugins/preauth/fast_factor.h | 53 + .../src/plugins/preauth/pkinit/Makefile.in | 58 + krb5-1-7/src/plugins/preauth/pkinit/deps | 57 + krb5-1-7/src/plugins/preauth/pkinit/pkcs11.h | 1357 ++ .../src/plugins/preauth/pkinit/pkinit.exports | 2 + krb5-1-7/src/plugins/preauth/pkinit/pkinit.h | 374 + .../plugins/preauth/pkinit/pkinit_accessor.c | 118 + .../plugins/preauth/pkinit/pkinit_accessor.h | 83 + .../src/plugins/preauth/pkinit/pkinit_clnt.c | 1504 ++ .../plugins/preauth/pkinit/pkinit_crypto.h | 623 + .../preauth/pkinit/pkinit_crypto_openssl.c | 5628 ++++++ .../preauth/pkinit/pkinit_crypto_openssl.h | 265 + .../plugins/preauth/pkinit/pkinit_identity.c | 668 + .../src/plugins/preauth/pkinit/pkinit_lib.c | 481 + .../plugins/preauth/pkinit/pkinit_matching.c | 829 + .../plugins/preauth/pkinit/pkinit_profile.c | 372 + .../src/plugins/preauth/pkinit/pkinit_srv.c | 1369 ++ krb5-1-7/src/plugins/preauth/wpse/Makefile.in | 41 + krb5-1-7/src/plugins/preauth/wpse/deps | 7 + .../src/plugins/preauth/wpse/wpse.exports | 2 + krb5-1-7/src/plugins/preauth/wpse/wpse_main.c | 470 + krb5-1-7/src/prototype/getopt.c | 29 + krb5-1-7/src/prototype/prototype.c | 30 + krb5-1-7/src/prototype/prototype.h | 33 + krb5-1-7/src/slave/Makefile.in | 45 + krb5-1-7/src/slave/deps | 59 + krb5-1-7/src/slave/kprop.M | 67 + krb5-1-7/src/slave/kprop.c | 747 + krb5-1-7/src/slave/kprop.h | 38 + krb5-1-7/src/slave/kpropd.M | 162 + krb5-1-7/src/slave/kpropd.c | 1684 ++ krb5-1-7/src/slave/kpropd_rpc.c | 55 + krb5-1-7/src/slave/kproplog.M | 96 + krb5-1-7/src/slave/kproplog.c | 590 + krb5-1-7/src/slave/kslave_update | 30 + krb5-1-7/src/t_krbconf | 38 + krb5-1-7/src/tests/Makefile.in | 68 + krb5-1-7/src/tests/asn.1/Makefile.in | 80 + krb5-1-7/src/tests/asn.1/README | 28 + krb5-1-7/src/tests/asn.1/debug.h | 20 + krb5-1-7/src/tests/asn.1/deps | 62 + krb5-1-7/src/tests/asn.1/krb5_decode_test.c | 932 + krb5-1-7/src/tests/asn.1/krb5_encode_test.c | 713 + krb5-1-7/src/tests/asn.1/ktest.c | 1435 ++ krb5-1-7/src/tests/asn.1/ktest.h | 225 + krb5-1-7/src/tests/asn.1/ktest_equal.c | 708 + krb5-1-7/src/tests/asn.1/ktest_equal.h | 96 + krb5-1-7/src/tests/asn.1/ldap_encode.out | 1 + krb5-1-7/src/tests/asn.1/ldap_trval.out | 30 + krb5-1-7/src/tests/asn.1/reference_encode.out | 58 + krb5-1-7/src/tests/asn.1/t_trval.c | 107 + krb5-1-7/src/tests/asn.1/trval.c | 767 + krb5-1-7/src/tests/asn.1/trval_reference.out | 1248 ++ krb5-1-7/src/tests/asn.1/utility.c | 135 + krb5-1-7/src/tests/asn.1/utility.h | 35 + krb5-1-7/src/tests/create/Makefile.in | 21 + krb5-1-7/src/tests/create/deps | 13 + krb5-1-7/src/tests/create/kdb5_mkdums.M | 141 + krb5-1-7/src/tests/create/kdb5_mkdums.c | 427 + krb5-1-7/src/tests/dejagnu/Makefile.in | 49 + krb5-1-7/src/tests/dejagnu/config/default.exp | 2817 +++ krb5-1-7/src/tests/dejagnu/deps | 5 + .../src/tests/dejagnu/krb-root/rlogin.exp | 322 + .../src/tests/dejagnu/krb-root/telnet.exp | 451 + .../tests/dejagnu/krb-standalone/gssapi.exp | 328 + .../tests/dejagnu/krb-standalone/gssftp.exp | 507 + .../tests/dejagnu/krb-standalone/iprop.exp | 238 + .../tests/dejagnu/krb-standalone/kadmin.exp | 1084 ++ .../tests/dejagnu/krb-standalone/kprop.exp | 155 + .../dejagnu/krb-standalone/princexpire.exp | 105 + .../tests/dejagnu/krb-standalone/pwchange.exp | 145 + .../tests/dejagnu/krb-standalone/pwhist.exp | 217 + .../src/tests/dejagnu/krb-standalone/rcp.exp | 231 + .../src/tests/dejagnu/krb-standalone/rsh.exp | 294 + .../tests/dejagnu/krb-standalone/sample.exp | 217 + .../tests/dejagnu/krb-standalone/simple.exp | 214 + .../dejagnu/krb-standalone/standalone.exp | 263 + .../src/tests/dejagnu/krb-standalone/tcp.exp | 117 + krb5-1-7/src/tests/dejagnu/t_inetd.c | 140 + krb5-1-7/src/tests/deps | 1 + krb5-1-7/src/tests/dump.c | 43 + krb5-1-7/src/tests/gss-threads/Makefile.in | 38 + krb5-1-7/src/tests/gss-threads/README | 165 + krb5-1-7/src/tests/gss-threads/deps | 15 + krb5-1-7/src/tests/gss-threads/gss-client.c | 883 + krb5-1-7/src/tests/gss-threads/gss-misc.c | 423 + krb5-1-7/src/tests/gss-threads/gss-misc.h | 60 + krb5-1-7/src/tests/gss-threads/gss-server.c | 852 + krb5-1-7/src/tests/gssapi/Makefile.in | 20 + krb5-1-7/src/tests/gssapi/deps | 5 + krb5-1-7/src/tests/gssapi/t_imp_name.c | 150 + krb5-1-7/src/tests/hammer/Makefile.in | 19 + krb5-1-7/src/tests/hammer/deps | 13 + krb5-1-7/src/tests/hammer/kdc5_hammer.c | 528 + krb5-1-7/src/tests/hammer/pp.c | 28 + .../input_conf/kdc_pri_template.conf | 13 + .../input_conf/kdc_ref_template.conf | 13 + .../input_conf/krb5_priCL_template.conf | 34 + .../input_conf/krb5_priKDC_1_template.conf | 30 + .../input_conf/krb5_priKDC_2_template.conf | 31 + .../input_conf/krb5_priKDC_3_template.conf | 30 + .../input_conf/krb5_priKDC_4_template.conf | 30 + .../input_conf/krb5_priKDC_5_template.conf | 30 + .../input_conf/krb5_priKDC_6_template.conf | 31 + .../input_conf/krb5_priKDC_7_template.conf | 29 + .../input_conf/krb5_priKDC_8_template.conf | 33 + .../input_conf/krb5_priKDC_template.conf | 30 + .../input_conf/krb5_ref_template.conf | 27 + .../tests/kdc_realm/input_conf/test_KDCs.conf | 9 + .../kdc_realm/input_conf/test_KDCs_1.conf | 9 + .../kdc_realm/input_conf/test_princs.conf | 1 + .../kdc_realm/input_conf/test_setup.conf | 6 + krb5-1-7/src/tests/kdc_realm/kdcref.py | 335 + krb5-1-7/src/tests/misc/Makefile.in | 55 + krb5-1-7/src/tests/misc/deps | 30 + krb5-1-7/src/tests/misc/test_cxx_gss.cpp | 10 + krb5-1-7/src/tests/misc/test_cxx_k5int.cpp | 19 + krb5-1-7/src/tests/misc/test_cxx_kadm5.cpp | 15 + krb5-1-7/src/tests/misc/test_cxx_krb5.cpp | 18 + krb5-1-7/src/tests/misc/test_cxx_rpc.cpp | 14 + krb5-1-7/src/tests/misc/test_getpw.c | 25 + krb5-1-7/src/tests/misc/test_getsockname.c | 91 + krb5-1-7/src/tests/misc/test_nfold.c | 65 + .../src/tests/mkeystash_compat/Makefile.in | 52 + .../src/tests/mkeystash_compat/bigendian.c | 17 + krb5-1-7/src/tests/mkeystash_compat/deps | 4 + .../tests/mkeystash_compat/old_stash_bendian | Bin 0 -> 67 bytes .../tests/mkeystash_compat/old_stash_lendian | Bin 0 -> 30 bytes krb5-1-7/src/tests/resolve/Makefile.in | 33 + krb5-1-7/src/tests/resolve/addrinfo-test.c | 316 + krb5-1-7/src/tests/resolve/deps | 12 + .../src/tests/resolve/fake-addrinfo-test.c | 2 + krb5-1-7/src/tests/resolve/resolve.c | 172 + krb5-1-7/src/tests/shlib/Makefile.in | 29 + krb5-1-7/src/tests/shlib/deps | 7 + krb5-1-7/src/tests/shlib/t_loader.c | 365 + krb5-1-7/src/tests/test1.c | 195 + krb5-1-7/src/tests/threads/Makefile.in | 38 + krb5-1-7/src/tests/threads/deps | 13 + krb5-1-7/src/tests/threads/prof1.c | 79 + krb5-1-7/src/tests/threads/t_rcache.c | 182 + krb5-1-7/src/tests/verify/Makefile.in | 20 + krb5-1-7/src/tests/verify/deps | 13 + krb5-1-7/src/tests/verify/kdb5_verify.c | 474 + krb5-1-7/src/tests/verify/pkey.c | 24 + krb5-1-7/src/util/Makefile.in | 53 + krb5-1-7/src/util/ac_check_krb5.m4 | 58 + krb5-1-7/src/util/check-ac-syms | 33 + .../src/util/collected-client-lib/Makefile.in | 79 + krb5-1-7/src/util/collected-client-lib/deps | 1 + .../collected-client-lib/libcollected.exports | 285 + krb5-1-7/src/util/def-check.pl | 265 + krb5-1-7/src/util/depfix.pl | 223 + krb5-1-7/src/util/deps | 1 + krb5-1-7/src/util/et/ISSUES | 60 + krb5-1-7/src/util/et/Makefile.in | 250 + krb5-1-7/src/util/et/com_err.3 | 96 + krb5-1-7/src/util/et/com_err.c | 175 + krb5-1-7/src/util/et/com_err.h | 80 + krb5-1-7/src/util/et/com_err.texinfo | 555 + krb5-1-7/src/util/et/compile_et.1 | 79 + krb5-1-7/src/util/et/compile_et.c | 348 + krb5-1-7/src/util/et/compile_et.sh | 24 + krb5-1-7/src/util/et/compiler.h | 14 + krb5-1-7/src/util/et/config_script | 22 + krb5-1-7/src/util/et/deps | 12 + krb5-1-7/src/util/et/error_message.c | 352 + krb5-1-7/src/util/et/error_table.h | 39 + krb5-1-7/src/util/et/error_table.y | 225 + krb5-1-7/src/util/et/et.exp | 8 + krb5-1-7/src/util/et/et.pbexp | 10 + krb5-1-7/src/util/et/et1.et | 11 + krb5-1-7/src/util/et/et2.et | 11 + krb5-1-7/src/util/et/et_c.awk | 213 + krb5-1-7/src/util/et/et_c.pl | 289 + krb5-1-7/src/util/et/et_h.awk | 168 + krb5-1-7/src/util/et/et_h.pl | 234 + krb5-1-7/src/util/et/et_lex.lex.l | 23 + krb5-1-7/src/util/et/et_name.c | 56 + krb5-1-7/src/util/et/init_et.c | 108 + krb5-1-7/src/util/et/internal.h | 17 + krb5-1-7/src/util/et/libcom_err.exports | 9 + krb5-1-7/src/util/et/mit-sipb-copyright.h | 22 + krb5-1-7/src/util/et/t_com_err.c | 143 + krb5-1-7/src/util/et/test1.et | 69 + krb5-1-7/src/util/et/test2.et | 9 + krb5-1-7/src/util/et/test_et.c | 76 + krb5-1-7/src/util/et/texinfo.tex | 2077 +++ krb5-1-7/src/util/exitsleep.c | 47 + krb5-1-7/src/util/export-check.pl | 79 + krb5-1-7/src/util/find-missing-eol-prop | 8 + krb5-1-7/src/util/fix-eol-prop | 13 + krb5-1-7/src/util/gen-map.pl | 111 + krb5-1-7/src/util/gen.pl | 61 + krb5-1-7/src/util/getsyms | 63 + krb5-1-7/src/util/getsyms.sed | 42 + krb5-1-7/src/util/kbuild | 168 + krb5-1-7/src/util/kfrags/athena.conf | 1 + krb5-1-7/src/util/kfrags/base.conf | 16 + krb5-1-7/src/util/kfrags/cns.conf | 1 + krb5-1-7/src/util/kfrags/gcc.conf | 2 + krb5-1-7/src/util/kfrags/ranlib.conf | 1 + krb5-1-7/src/util/kfrags/shared.conf | 4 + krb5-1-7/src/util/kfrags/sunpro.conf | 1 + krb5-1-7/src/util/kfrags/svr4.conf | 1 + krb5-1-7/src/util/kfrags/ucb.conf | 2 + krb5-1-7/src/util/ktemplate.pm | 74 + krb5-1-7/src/util/lndir | 103 + krb5-1-7/src/util/mac/k5_mig.defs | 54 + krb5-1-7/src/util/mac/k5_mig_client.c | 529 + krb5-1-7/src/util/mac/k5_mig_client.h | 37 + krb5-1-7/src/util/mac/k5_mig_reply.defs | 58 + krb5-1-7/src/util/mac/k5_mig_request.defs | 62 + krb5-1-7/src/util/mac/k5_mig_server.c | 390 + krb5-1-7/src/util/mac/k5_mig_server.h | 52 + krb5-1-7/src/util/mac/k5_mig_types.h | 59 + krb5-1-7/src/util/mkrel | 224 + krb5-1-7/src/util/profile/Makefile.in | 156 + krb5-1-7/src/util/profile/argv_parse.c | 168 + krb5-1-7/src/util/profile/argv_parse.h | 43 + krb5-1-7/src/util/profile/deps | 39 + krb5-1-7/src/util/profile/dosshell.ini | 537 + krb5-1-7/src/util/profile/krb5.conf | 55 + krb5-1-7/src/util/profile/libprofile.exports | 55 + krb5-1-7/src/util/profile/prof_FSp_glue.c | 91 + krb5-1-7/src/util/profile/prof_err.et | 66 + krb5-1-7/src/util/profile/prof_file.c | 609 + krb5-1-7/src/util/profile/prof_get.c | 458 + krb5-1-7/src/util/profile/prof_init.c | 402 + krb5-1-7/src/util/profile/prof_int.h | 253 + krb5-1-7/src/util/profile/prof_parse.c | 496 + krb5-1-7/src/util/profile/prof_set.c | 286 + krb5-1-7/src/util/profile/prof_test1 | 154 + krb5-1-7/src/util/profile/prof_tree.c | 708 + krb5-1-7/src/util/profile/profile.5 | 71 + krb5-1-7/src/util/profile/profile.exp | 35 + krb5-1-7/src/util/profile/profile.hin | 125 + krb5-1-7/src/util/profile/profile.pbexp | 33 + krb5-1-7/src/util/profile/profile.swg | 258 + krb5-1-7/src/util/profile/profile_tcl.c | 2159 +++ krb5-1-7/src/util/profile/prtest.in | 36 + krb5-1-7/src/util/profile/prtest.script | 11 + krb5-1-7/src/util/profile/test.ini | 47 + krb5-1-7/src/util/profile/test_parse.c | 54 + krb5-1-7/src/util/profile/test_profile.c | 169 + krb5-1-7/src/util/reconf | 106 + krb5-1-7/src/util/send-pr/COPYING | 339 + krb5-1-7/src/util/send-pr/INSTALL | 83 + krb5-1-7/src/util/send-pr/MANIFEST | 20 + krb5-1-7/src/util/send-pr/Makefile.in | 48 + krb5-1-7/src/util/send-pr/README | 43 + krb5-1-7/src/util/send-pr/categories | 11 + krb5-1-7/src/util/send-pr/deps | 1 + krb5-1-7/src/util/send-pr/install-sid.sh | 86 + krb5-1-7/src/util/send-pr/send-pr.1 | 289 + krb5-1-7/src/util/send-pr/send-pr.sh | 542 + krb5-1-7/src/util/ss/Makefile.in | 172 + krb5-1-7/src/util/ss/cmd_tbl.lex.l | 81 + krb5-1-7/src/util/ss/config_script | 28 + krb5-1-7/src/util/ss/copyright.h | 22 + krb5-1-7/src/util/ss/ct.y | 81 + krb5-1-7/src/util/ss/ct_c_awk.in | 77 + krb5-1-7/src/util/ss/ct_c_sed.in | 161 + krb5-1-7/src/util/ss/data.c | 16 + krb5-1-7/src/util/ss/deps | 68 + krb5-1-7/src/util/ss/error.c | 71 + krb5-1-7/src/util/ss/execute_cmd.c | 204 + krb5-1-7/src/util/ss/help.c | 155 + krb5-1-7/src/util/ss/invocation.c | 130 + krb5-1-7/src/util/ss/list_rqs.c | 120 + krb5-1-7/src/util/ss/listen.c | 169 + krb5-1-7/src/util/ss/mit-sipb-copyright.h | 22 + krb5-1-7/src/util/ss/mk_cmds.c | 102 + krb5-1-7/src/util/ss/mk_cmds.sh | 29 + krb5-1-7/src/util/ss/options.c | 32 + krb5-1-7/src/util/ss/pager.c | 111 + krb5-1-7/src/util/ss/parse.c | 170 + krb5-1-7/src/util/ss/prompt.c | 28 + krb5-1-7/src/util/ss/request_tbl.c | 65 + krb5-1-7/src/util/ss/requests.c | 47 + krb5-1-7/src/util/ss/ss.h | 71 + krb5-1-7/src/util/ss/ss_err.et | 39 + krb5-1-7/src/util/ss/ss_internal.h | 124 + krb5-1-7/src/util/ss/std_rqs.ct | 46 + krb5-1-7/src/util/ss/test_ss.c | 99 + krb5-1-7/src/util/ss/utils.c | 109 + krb5-1-7/src/util/support/Makefile.in | 145 + krb5-1-7/src/util/support/cache-addrinfo.h | 128 + krb5-1-7/src/util/support/deps | 46 + krb5-1-7/src/util/support/errors.c | 220 + krb5-1-7/src/util/support/fake-addrinfo.c | 1386 ++ krb5-1-7/src/util/support/gmt_mktime.c | 129 + krb5-1-7/src/util/support/init-addrinfo.c | 70 + krb5-1-7/src/util/support/ipc_stream.c | 465 + krb5-1-7/src/util/support/k5buf-int.h | 51 + krb5-1-7/src/util/support/k5buf.c | 213 + .../util/support/libkrb5support-fixed.exports | 50 + krb5-1-7/src/util/support/mkstemp.c | 137 + krb5-1-7/src/util/support/plugins.c | 787 + krb5-1-7/src/util/support/printf.c | 101 + krb5-1-7/src/util/support/strlcpy.c | 88 + krb5-1-7/src/util/support/supp-int.h | 36 + krb5-1-7/src/util/support/t_k5buf.c | 287 + krb5-1-7/src/util/support/threads.c | 527 + krb5-1-7/src/util/support/utf8.c | 549 + krb5-1-7/src/util/support/utf8_conv.c | 455 + krb5-1-7/src/util/t_array.pm | 132 + krb5-1-7/src/util/t_bimap.pm | 194 + krb5-1-7/src/util/t_enum.pm | 133 + krb5-1-7/src/util/t_template.pm | 61 + krb5-1-7/src/util/t_tsenum.pm | 163 + krb5-1-7/src/util/trim-valgrind-logs | 71 + krb5-1-7/src/util/valgrind-suppressions | 85 + krb5-1-7/src/util/windows/Makefile.in | 16 + krb5-1-7/src/util/windows/getopt.c | 152 + krb5-1-7/src/util/windows/getopt.h | 33 + krb5-1-7/src/util/windows/getopt_long.c | 236 + krb5-1-7/src/util/windows/libecho.c | 76 + krb5-1-7/src/wconfig.c | 231 + krb5-1-7/src/windows/Makefile.in | 76 + krb5-1-7/src/windows/README | 305 + krb5-1-7/src/windows/build/BKWconfig.xml | 172 + krb5-1-7/src/windows/build/Logger.pm | 87 + .../src/windows/build/bkw-automation.html | 367 + krb5-1-7/src/windows/build/bkw.pl | 704 + krb5-1-7/src/windows/build/bootstrap.xml | 19 + .../src/windows/build/commandandcontrol.pl | 170 + krb5-1-7/src/windows/build/copyfiles.pl | 137 + krb5-1-7/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-7/src/windows/build/makeZip.pl | 84 + krb5-1-7/src/windows/build/pruneFiles.pl | 36 + krb5-1-7/src/windows/build/repository1.pl | 90 + krb5-1-7/src/windows/build/sdkfiles.xml | 23 + krb5-1-7/src/windows/build/signFiles.pl | 27 + krb5-1-7/src/windows/build/site-local.sed | 2 + krb5-1-7/src/windows/build/tee.pl | 79 + krb5-1-7/src/windows/build/which.pl | 69 + krb5-1-7/src/windows/build/zipXML.pl | 21 + krb5-1-7/src/windows/cns/Makefile.in | 76 + krb5-1-7/src/windows/cns/clock00.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock05.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock10.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock15.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock20.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock25.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock30.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock35.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock40.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock45.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock50.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock55.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clock60.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clockexp.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/clocktkt.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/cns-help.doc | Bin 0 -> 22528 bytes krb5-1-7/src/windows/cns/cns-help.hlp | Bin 0 -> 11944 bytes krb5-1-7/src/windows/cns/cns-help.hpj | 133 + krb5-1-7/src/windows/cns/cns.c | 2208 +++ krb5-1-7/src/windows/cns/cns.h | 249 + krb5-1-7/src/windows/cns/cns.ico | Bin 0 -> 1086 bytes krb5-1-7/src/windows/cns/cns_reg.c | 230 + krb5-1-7/src/windows/cns/cns_reg.h | 33 + krb5-1-7/src/windows/cns/cnsres4.rc | 108 + krb5-1-7/src/windows/cns/cnsres5.rc | 215 + krb5-1-7/src/windows/cns/debug.c | 91 + krb5-1-7/src/windows/cns/heap.c | 33 + krb5-1-7/src/windows/cns/kerbnet.doc | Bin 0 -> 22528 bytes krb5-1-7/src/windows/cns/kerbnet.hlp | Bin 0 -> 16334 bytes krb5-1-7/src/windows/cns/kerbnet.hpj | 133 + krb5-1-7/src/windows/cns/kpasswd.c | 90 + krb5-1-7/src/windows/cns/krb5.def | 9 + krb5-1-7/src/windows/cns/krbini.h | 37 + krb5-1-7/src/windows/cns/options.c | 232 + krb5-1-7/src/windows/cns/password.c | 323 + krb5-1-7/src/windows/cns/tktlist.c | 442 + krb5-1-7/src/windows/cns/tktlist.h | 27 + krb5-1-7/src/windows/gina/Makefile.in | 36 + krb5-1-7/src/windows/gina/gina.def | 21 + krb5-1-7/src/windows/gina/ginastub.c | 365 + krb5-1-7/src/windows/gina/ginastub.h | 39 + krb5-1-7/src/windows/gss/Makefile.in | 52 + krb5-1-7/src/windows/gss/gss-client.c | 615 + krb5-1-7/src/windows/gss/gss-misc.c | 429 + krb5-1-7/src/windows/gss/gss-misc.h | 60 + krb5-1-7/src/windows/gss/gss.c | 722 + krb5-1-7/src/windows/gss/gss.def | 15 + krb5-1-7/src/windows/gss/gss.h | 43 + krb5-1-7/src/windows/gss/gss.ico | Bin 0 -> 1022 bytes krb5-1-7/src/windows/gss/gss.rc | 148 + krb5-1-7/src/windows/gss/resource.h | 50 + krb5-1-7/src/windows/gss/ver_serv.txt | 11 + krb5-1-7/src/windows/identity/Makefile | 214 + krb5-1-7/src/windows/identity/apiversion.txt | 367 + krb5-1-7/src/windows/identity/config/Makefile | 147 + .../src/windows/identity/config/Makefile.w2k | 306 + .../src/windows/identity/config/Makefile.w32 | 344 + krb5-1-7/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-7/src/windows/identity/doc/Makefile | 71 + .../windows/identity/doc/cred_aquisition.h | 325 + .../windows/identity/doc/cred_data_types.h | 264 + krb5-1-7/src/windows/identity/doc/cred_main.h | 36 + krb5-1-7/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-7/src/windows/identity/doc/footer.html | 21 + krb5-1-7/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-7/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-7/src/windows/identity/doc/ui_main.h | 36 + krb5-1-7/src/windows/identity/doc/ui_menus.h | 30 + krb5-1-7/src/windows/identity/help/Index.hhk | 9 + krb5-1-7/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-7/src/windows/identity/help/khhelp.h | 33 + .../src/windows/identity/help/netidmgr.hhp | 35 + krb5-1-7/src/windows/identity/help/popups.txt | 1 + .../windows/identity/help/popups_newcreds.txt | 30 + .../windows/identity/help/popups_password.txt | 19 + krb5-1-7/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-7/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-7/src/windows/identity/kcreddb/buf.c | 391 + krb5-1-7/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-7/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-7/src/windows/identity/kcreddb/type.c | 1386 ++ krb5-1-7/src/windows/identity/kcreddb/type.h | 216 + krb5-1-7/src/windows/identity/kherr/Makefile | 44 + krb5-1-7/src/windows/identity/kherr/kherr.c | 1580 ++ krb5-1-7/src/windows/identity/kherr/kherr.h | 1126 ++ .../windows/identity/kherr/kherrinternal.h | 74 + .../src/windows/identity/kherr/kherrmain.c | 52 + krb5-1-7/src/windows/identity/kmm/Makefile | 55 + krb5-1-7/src/windows/identity/kmm/kmm.c | 192 + krb5-1-7/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-7/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-7/src/windows/identity/kmm/kmmmain.c | 161 + krb5-1-7/src/windows/identity/kmm/kplugin.h | 146 + .../src/windows/identity/kmm/lang/kmm_msgs.mc | 259 + krb5-1-7/src/windows/identity/kmq/Makefile | 49 + krb5-1-7/src/windows/identity/kmq/consumer.c | 572 + krb5-1-7/src/windows/identity/kmq/init.c | 310 + krb5-1-7/src/windows/identity/kmq/kmq.h | 713 + .../src/windows/identity/kmq/kmqconfig.csv | 5 + .../src/windows/identity/kmq/kmqinternal.h | 241 + krb5-1-7/src/windows/identity/kmq/kmqmain.c | 47 + krb5-1-7/src/windows/identity/kmq/msgtype.c | 394 + krb5-1-7/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 | 485 + .../identity/plugins/common/dynimport.h | 368 + .../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 | 3637 ++++ .../windows/identity/plugins/krb5/krb5funcs.h | 224 + .../identity/plugins/krb5/krb5identpro.c | 1861 ++ .../windows/identity/plugins/krb5/krb5main.c | 497 + .../identity/plugins/krb5/krb5newcreds.c | 2925 ++++ .../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 | 243 + .../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-7/src/windows/identity/ui/Makefile | 109 + krb5-1-7/src/windows/identity/ui/Makefile.w2k | 91 + krb5-1-7/src/windows/identity/ui/aboutwnd.c | 154 + krb5-1-7/src/windows/identity/ui/aboutwnd.h | 33 + krb5-1-7/src/windows/identity/ui/addrchange.c | 93 + krb5-1-7/src/windows/identity/ui/addrchange.h | 36 + krb5-1-7/src/windows/identity/ui/appglobal.h | 163 + krb5-1-7/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-7/src/windows/identity/ui/configwnd.c | 1243 ++ krb5-1-7/src/windows/identity/ui/configwnd.h | 88 + krb5-1-7/src/windows/identity/ui/credfuncs.c | 1415 ++ krb5-1-7/src/windows/identity/ui/credfuncs.h | 95 + krb5-1-7/src/windows/identity/ui/credwnd.c | 5952 +++++++ krb5-1-7/src/windows/identity/ui/credwnd.h | 306 + krb5-1-7/src/windows/identity/ui/debugfuncs.c | 256 + krb5-1-7/src/windows/identity/ui/debugfuncs.h | 37 + krb5-1-7/src/windows/identity/ui/htwnd.c | 1311 ++ krb5-1-7/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-7/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-7/src/windows/identity/ui/main.c | 1075 ++ krb5-1-7/src/windows/identity/ui/mainmenu.c | 1233 ++ krb5-1-7/src/windows/identity/ui/mainmenu.h | 68 + krb5-1-7/src/windows/identity/ui/mainwnd.c | 1380 ++ krb5-1-7/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-7/src/windows/identity/ui/newcredwnd.c | 3034 ++++ krb5-1-7/src/windows/identity/ui/newcredwnd.h | 193 + krb5-1-7/src/windows/identity/ui/notifier.c | 3174 ++++ krb5-1-7/src/windows/identity/ui/notifier.h | 69 + krb5-1-7/src/windows/identity/ui/passwnd.c | 133 + krb5-1-7/src/windows/identity/ui/passwnd.h | 39 + .../src/windows/identity/ui/propertywnd.c | 254 + .../src/windows/identity/ui/propertywnd.h | 36 + krb5-1-7/src/windows/identity/ui/reqdaemon.c | 453 + krb5-1-7/src/windows/identity/ui/reqdaemon.h | 42 + krb5-1-7/src/windows/identity/ui/resource.h | 421 + krb5-1-7/src/windows/identity/ui/statusbar.c | 208 + krb5-1-7/src/windows/identity/ui/statusbar.h | 55 + krb5-1-7/src/windows/identity/ui/taskbar.c | 87 + krb5-1-7/src/windows/identity/ui/taskbar.h | 38 + krb5-1-7/src/windows/identity/ui/timer.c | 1015 ++ krb5-1-7/src/windows/identity/ui/timer.h | 100 + krb5-1-7/src/windows/identity/ui/toolbar.c | 471 + krb5-1-7/src/windows/identity/ui/toolbar.h | 52 + krb5-1-7/src/windows/identity/ui/uiconfig.csv | 273 + krb5-1-7/src/windows/identity/uilib/Makefile | 68 + krb5-1-7/src/windows/identity/uilib/accel.csv | 26 + .../src/windows/identity/uilib/acceldef.cfg | 51 + krb5-1-7/src/windows/identity/uilib/action.c | 1672 ++ .../src/windows/identity/uilib/actiondef.cfg | 67 + .../src/windows/identity/uilib/actions.csv | 55 + krb5-1-7/src/windows/identity/uilib/alert.c | 440 + .../src/windows/identity/uilib/configui.c | 1088 ++ .../src/windows/identity/uilib/configui.h | 74 + krb5-1-7/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-7/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-7/src/windows/identity/uilib/propwnd.c | 39 + .../src/windows/identity/uilib/rescache.c | 304 + .../src/windows/identity/uilib/trackerwnd.c | 477 + krb5-1-7/src/windows/identity/uilib/uibind.c | 62 + .../src/windows/identity/uilib/uilibmain.c | 46 + krb5-1-7/src/windows/identity/uilib/version.c | 85 + krb5-1-7/src/windows/identity/util/Makefile | 49 + .../src/windows/identity/util/hashtable.c | 173 + .../src/windows/identity/util/hashtable.h | 231 + krb5-1-7/src/windows/identity/util/mstring.c | 512 + krb5-1-7/src/windows/identity/util/mstring.h | 361 + krb5-1-7/src/windows/identity/util/perfstat.c | 459 + krb5-1-7/src/windows/identity/util/perfstat.h | 74 + krb5-1-7/src/windows/identity/util/sync.c | 132 + krb5-1-7/src/windows/identity/util/sync.h | 128 + krb5-1-7/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-7/src/windows/installer/nsis/kfw.ico | Bin 0 -> 25214 bytes krb5-1-7/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-7/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-7/src/windows/installer/wix/Makefile | 59 + krb5-1-7/src/windows/installer/wix/config.wxi | 179 + .../windows/installer/wix/custom/custom.cpp | 759 + .../src/windows/installer/wix/custom/custom.h | 82 + .../src/windows/installer/wix/features.wxi | 232 + krb5-1-7/src/windows/installer/wix/files.wxi | 1103 ++ krb5-1-7/src/windows/installer/wix/kfw.wxs | 246 + .../installer/wix/lang/config_1033.wxi | 76 + .../windows/installer/wix/lang/license.rtf | 102 + .../installer/wix/lang/strings_1033.wxl | 68 + .../windows/installer/wix/lang/ui_1033.wxi | 1240 ++ .../installer/wix/msi-deployment-guide.txt | 946 + .../src/windows/installer/wix/platform.wxi | 197 + .../src/windows/installer/wix/property.wxi | 96 + .../src/windows/installer/wix/runtime.wxi | 90 + .../windows/installer/wix/runtime_debug.wxi | 14 + .../installer/wix/site-local-tagged.wxi | 105 + krb5-1-7/src/windows/kfwlogon/Makefile.in | 47 + krb5-1-7/src/windows/kfwlogon/kfwcommon.c | 1352 ++ krb5-1-7/src/windows/kfwlogon/kfwcpcc.c | 39 + krb5-1-7/src/windows/kfwlogon/kfwlogon.c | 634 + krb5-1-7/src/windows/kfwlogon/kfwlogon.def | 14 + krb5-1-7/src/windows/kfwlogon/kfwlogon.h | 215 + krb5-1-7/src/windows/lib/Makefile.in | 17 + krb5-1-7/src/windows/lib/cacheapi.h | 458 + krb5-1-7/src/windows/lib/gic.c | 157 + krb5-1-7/src/windows/lib/gic.h | 28 + krb5-1-7/src/windows/lib/registry.c | 231 + krb5-1-7/src/windows/lib/registry.h | 40 + krb5-1-7/src/windows/lib/vardlg.c | 453 + krb5-1-7/src/windows/lib/vardlg.h | 32 + krb5-1-7/src/windows/ms2mit/Makefile.in | 41 + krb5-1-7/src/windows/ms2mit/mit2ms.c | 149 + krb5-1-7/src/windows/ms2mit/ms2mit.c | 171 + krb5-1-7/src/windows/ntsecapitest.c | 11 + krb5-1-7/src/windows/ntsecapitest.pl | 11 + krb5-1-7/src/windows/version.rc | 329 + krb5-1-7/src/windows/winlevel.h | 33 + krb5-1-7/src/windows/wintel/Makefile.in | 46 + krb5-1-7/src/windows/wintel/auth.c | 867 + krb5-1-7/src/windows/wintel/auth.h | 28 + krb5-1-7/src/windows/wintel/dialog.h | 42 + krb5-1-7/src/windows/wintel/edit.c | 444 + krb5-1-7/src/windows/wintel/emul.c | 766 + krb5-1-7/src/windows/wintel/enc_des.c | 725 + krb5-1-7/src/windows/wintel/enc_des.h | 120 + krb5-1-7/src/windows/wintel/encrypt.c | 999 ++ krb5-1-7/src/windows/wintel/encrypt.h | 178 + krb5-1-7/src/windows/wintel/font.c | 100 + krb5-1-7/src/windows/wintel/genget.c | 101 + krb5-1-7/src/windows/wintel/ini.h | 16 + krb5-1-7/src/windows/wintel/intern.c | 815 + krb5-1-7/src/windows/wintel/k5stream.c | 119 + krb5-1-7/src/windows/wintel/k5stream.h | 57 + krb5-1-7/src/windows/wintel/ktelnet.doc | Bin 0 -> 16384 bytes krb5-1-7/src/windows/wintel/ktelnet.hlp | Bin 0 -> 9204 bytes krb5-1-7/src/windows/wintel/ktelnet.hpj | 92 + krb5-1-7/src/windows/wintel/ncsa.ico | Bin 0 -> 766 bytes krb5-1-7/src/windows/wintel/negotiat.c | 865 + krb5-1-7/src/windows/wintel/resource.h | 17 + krb5-1-7/src/windows/wintel/screen.c | 1147 ++ krb5-1-7/src/windows/wintel/screen.h | 325 + krb5-1-7/src/windows/wintel/struct.h | 29 + krb5-1-7/src/windows/wintel/telnet.c | 904 + krb5-1-7/src/windows/wintel/telnet.def | 39 + krb5-1-7/src/windows/wintel/telnet.h | 41 + krb5-1-7/src/windows/wintel/telnet.rc | 247 + krb5-1-7/src/windows/wintel/telnet_arpa.h | 327 + krb5-1-7/src/windows/wintel/telopts.h | 164 + krb5-1-7/src/windows/wintel/terminal.ico | Bin 0 -> 766 bytes krb5-1-7/src/windows/wintel/wt-proto.h | 63 + 2891 files changed, 845431 insertions(+) create mode 100644 krb5-1-7/README create mode 100644 krb5-1-7/doc/Makefile create mode 100644 krb5-1-7/doc/admin.texinfo create mode 100644 krb5-1-7/doc/api/Makefile create mode 100644 krb5-1-7/doc/api/ccache.tex create mode 100644 krb5-1-7/doc/api/errors.tex create mode 100644 krb5-1-7/doc/api/fancyheadings.sty create mode 100644 krb5-1-7/doc/api/fixunder.sty create mode 100644 krb5-1-7/doc/api/free.tex create mode 100644 krb5-1-7/doc/api/functions.sty create mode 100644 krb5-1-7/doc/api/intro.tex create mode 100644 krb5-1-7/doc/api/keytab.tex create mode 100644 krb5-1-7/doc/api/krb5.ist create mode 100644 krb5-1-7/doc/api/krb5.tex create mode 100644 krb5-1-7/doc/api/krb5idx.sty create mode 100644 krb5-1-7/doc/api/libdes.tex create mode 100644 krb5-1-7/doc/api/libos.tex create mode 100644 krb5-1-7/doc/api/library.tex create mode 100644 krb5-1-7/doc/api/rcache.tex create mode 100644 krb5-1-7/doc/api/tables.tex create mode 100644 krb5-1-7/doc/bug-report.texinfo create mode 100644 krb5-1-7/doc/build.texinfo create mode 100644 krb5-1-7/doc/ccapi/Doxyfile create mode 100755 krb5-1-7/doc/ccapi/ccache-api-v2.html create mode 100644 krb5-1-7/doc/ccapi/html/doxygen.css create mode 100644 krb5-1-7/doc/ccapi/html/doxygen.png create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__ccache__iterator__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__ccache__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__context__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__credentials__iterator__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__credentials__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__cc__string__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__ccapi__constants__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__ccapi__types__reference.html create mode 100644 krb5-1-7/doc/ccapi/html/group__helper__macros.html create mode 100644 krb5-1-7/doc/ccapi/html/index.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__ccache__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__ccache__f.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__f.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__context__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__context__f.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__f.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__f.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__union.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__v4__t.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__credentials__v5__t.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__data.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__string__d.html create mode 100644 krb5-1-7/doc/ccapi/html/structcc__string__f.html create mode 100644 krb5-1-7/doc/coding-style create mode 100644 krb5-1-7/doc/contributing.txt create mode 100644 krb5-1-7/doc/copyright.texinfo create mode 100644 krb5-1-7/doc/definitions.texinfo create mode 100644 krb5-1-7/doc/dnssrv.texinfo create mode 100644 krb5-1-7/doc/dnstxt.texinfo create mode 100644 krb5-1-7/doc/document-list.texinfo create mode 100644 krb5-1-7/doc/glossary.texinfo create mode 100644 krb5-1-7/doc/implement/Makefile create mode 100644 krb5-1-7/doc/implement/ccache-i.tex create mode 100644 krb5-1-7/doc/implement/cksum-i.tex create mode 100644 krb5-1-7/doc/implement/crc-32-i.tex create mode 100644 krb5-1-7/doc/implement/encrypt-i.tex create mode 100644 krb5-1-7/doc/implement/fancyheadings.sty create mode 100644 krb5-1-7/doc/implement/fixunder.sty create mode 100644 krb5-1-7/doc/implement/functions.sty create mode 100644 krb5-1-7/doc/implement/implement.tex create mode 100644 krb5-1-7/doc/implement/kdb-i.tex create mode 100644 krb5-1-7/doc/implement/keytab-i.tex create mode 100644 krb5-1-7/doc/implement/libos-i.tex create mode 100644 krb5-1-7/doc/implement/rcache-i.tex create mode 100644 krb5-1-7/doc/implementor.texinfo create mode 100644 krb5-1-7/doc/install-old.texi create mode 100644 krb5-1-7/doc/install.texinfo create mode 100644 krb5-1-7/doc/iprop-notes.txt create mode 100644 krb5-1-7/doc/kadm5-errmsg.txt create mode 100644 krb5-1-7/doc/kadm5/adb-unit-test.tex create mode 100644 krb5-1-7/doc/kadm5/api-funcspec.tex create mode 100644 krb5-1-7/doc/kadm5/api-server-design.tex create mode 100644 krb5-1-7/doc/kadm5/api-unit-test.tex create mode 100644 krb5-1-7/doc/kadm5/fullpage.sty create mode 100644 krb5-1-7/doc/kadm5/rcsid.sty create mode 100644 krb5-1-7/doc/kadm5acl.texinfo create mode 100644 krb5-1-7/doc/kadmin/README create mode 100644 krb5-1-7/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt create mode 100644 krb5-1-7/doc/kadmin/kadmin.protocol create mode 100644 krb5-1-7/doc/kadmin/kpasswd.protocol create mode 100644 krb5-1-7/doc/kdcconf.texinfo create mode 100644 krb5-1-7/doc/kim/Doxyfile create mode 100644 krb5-1-7/doc/kim/html/doxygen.css create mode 100644 krb5-1-7/doc/kim/html/doxygen.png create mode 100644 krb5-1-7/doc/kim/html/group__kim__ccache__iterator__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__ccache__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__credential__iterator__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__credential__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__error__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__favorite__identities__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__identity__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__library__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__options__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__preferences__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__selection__hints__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__string__reference.html create mode 100644 krb5-1-7/doc/kim/html/group__kim__types__reference.html create mode 100644 krb5-1-7/doc/kim/html/index.html create mode 100644 krb5-1-7/doc/kim/html/kim_ccache_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_credential_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_error_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_favorite_identities_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_identity_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_options_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_preferences_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_selection_hints_overview.html create mode 100644 krb5-1-7/doc/kim/html/kim_string_overview.html create mode 100644 krb5-1-7/doc/kim/html/modules.html create mode 100644 krb5-1-7/doc/kim/html/tab_b.gif create mode 100644 krb5-1-7/doc/kim/html/tab_l.gif create mode 100644 krb5-1-7/doc/kim/html/tab_r.gif create mode 100644 krb5-1-7/doc/kim/html/tabs.css create mode 100644 krb5-1-7/doc/krb5-protocol/draft-ietf-cat-kerberos-pk-init-09.txt create mode 100755 krb5-1-7/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt create mode 100644 krb5-1-7/doc/krb5-protocol/krb5.constants create mode 100644 krb5-1-7/doc/krb5-protocol/rfc3961.txt create mode 100644 krb5-1-7/doc/krb5-protocol/rfc3962.txt create mode 100644 krb5-1-7/doc/krb5-protocol/rfc4120.txt create mode 100644 krb5-1-7/doc/krb5-protocol/rfc4121.txt create mode 100644 krb5-1-7/doc/krb5-protocol/rfc4557.txt create mode 100644 krb5-1-7/doc/krb5conf.texinfo create mode 100755 krb5-1-7/doc/man2html create mode 100644 krb5-1-7/doc/man2html.M create mode 100755 krb5-1-7/doc/man2ps create mode 100644 krb5-1-7/doc/man2ps.M create mode 100644 krb5-1-7/doc/procedures.txt create mode 100644 krb5-1-7/doc/rpc/design.tex create mode 100644 krb5-1-7/doc/salts.texinfo create mode 100644 krb5-1-7/doc/send-pr.texinfo create mode 100644 krb5-1-7/doc/support-enc.texinfo create mode 100644 krb5-1-7/doc/texinfo-suppl.tex create mode 100644 krb5-1-7/doc/texinfo.tex create mode 100644 krb5-1-7/doc/thread-safe.txt create mode 100644 krb5-1-7/doc/threads.txt create mode 100644 krb5-1-7/doc/user-guide.texinfo create mode 100644 krb5-1-7/src/BADSYMS create mode 100644 krb5-1-7/src/Makefile.in create mode 100644 krb5-1-7/src/aclocal.m4 create mode 100644 krb5-1-7/src/appl/Makefile.in create mode 100644 krb5-1-7/src/appl/bsd/Makefile.in create mode 100644 krb5-1-7/src/appl/bsd/configure.in create mode 100644 krb5-1-7/src/appl/bsd/defines.h create mode 100644 krb5-1-7/src/appl/bsd/deps create mode 100644 krb5-1-7/src/appl/bsd/forward.c create mode 100644 krb5-1-7/src/appl/bsd/getdtablesize.c create mode 100644 krb5-1-7/src/appl/bsd/kcmd.c create mode 100644 krb5-1-7/src/appl/bsd/klogind.M create mode 100644 krb5-1-7/src/appl/bsd/krcp.c create mode 100644 krb5-1-7/src/appl/bsd/krlogin.c create mode 100644 krb5-1-7/src/appl/bsd/krlogind.c create mode 100644 krb5-1-7/src/appl/bsd/krsh.c create mode 100644 krb5-1-7/src/appl/bsd/krshd.c create mode 100644 krb5-1-7/src/appl/bsd/kshd.M create mode 100644 krb5-1-7/src/appl/bsd/login.M create mode 100644 krb5-1-7/src/appl/bsd/login.c create mode 100644 krb5-1-7/src/appl/bsd/loginpaths.h create mode 100644 krb5-1-7/src/appl/bsd/rcp.M create mode 100644 krb5-1-7/src/appl/bsd/rlogin.M create mode 100644 krb5-1-7/src/appl/bsd/rpaths.h create mode 100644 krb5-1-7/src/appl/bsd/rsh.M create mode 100644 krb5-1-7/src/appl/bsd/setenv.c create mode 100644 krb5-1-7/src/appl/deps create mode 100644 krb5-1-7/src/appl/gss-sample/Makefile.in create mode 100644 krb5-1-7/src/appl/gss-sample/README create mode 100644 krb5-1-7/src/appl/gss-sample/deps create mode 100644 krb5-1-7/src/appl/gss-sample/gss-client.c create mode 100644 krb5-1-7/src/appl/gss-sample/gss-misc.c create mode 100644 krb5-1-7/src/appl/gss-sample/gss-misc.h create mode 100644 krb5-1-7/src/appl/gss-sample/gss-server.c create mode 100644 krb5-1-7/src/appl/gssftp/Makefile.in create mode 100644 krb5-1-7/src/appl/gssftp/README.gssftp create mode 100644 krb5-1-7/src/appl/gssftp/arpa/ftp.h create mode 100644 krb5-1-7/src/appl/gssftp/arpa/telnet.h create mode 100644 krb5-1-7/src/appl/gssftp/configure.in create mode 100644 krb5-1-7/src/appl/gssftp/deps create mode 100644 krb5-1-7/src/appl/gssftp/ftp/Makefile.in create mode 100644 krb5-1-7/src/appl/gssftp/ftp/cmds.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/cmdtab.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/deps create mode 100644 krb5-1-7/src/appl/gssftp/ftp/domacro.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/ftp.M create mode 100644 krb5-1-7/src/appl/gssftp/ftp/ftp.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/ftp_var.h create mode 100644 krb5-1-7/src/appl/gssftp/ftp/getpass.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/glob.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/main.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/pathnames.h create mode 100644 krb5-1-7/src/appl/gssftp/ftp/pclose.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/radix.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/ruserpass.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/secure.c create mode 100644 krb5-1-7/src/appl/gssftp/ftp/secure.h create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/CHANGES create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/Makefile.in create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/deps create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/ftpcmd.y create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/ftpd.M create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/ftpd.c create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/ftpd_var.h create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/logwtmp.c create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/pathnames.h create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/popen.c create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/secure.h create mode 100644 krb5-1-7/src/appl/gssftp/ftpd/vers.c create mode 100644 krb5-1-7/src/appl/libpty/Makefile.in create mode 100644 krb5-1-7/src/appl/libpty/README create mode 100644 krb5-1-7/src/appl/libpty/cleanup.c create mode 100644 krb5-1-7/src/appl/libpty/configure.in create mode 100644 krb5-1-7/src/appl/libpty/deps create mode 100644 krb5-1-7/src/appl/libpty/dump-utmp.c create mode 100644 krb5-1-7/src/appl/libpty/getpty.c create mode 100644 krb5-1-7/src/appl/libpty/init.c create mode 100644 krb5-1-7/src/appl/libpty/init_slave.c create mode 100644 krb5-1-7/src/appl/libpty/libpty.h create mode 100644 krb5-1-7/src/appl/libpty/logwtmp.c create mode 100644 krb5-1-7/src/appl/libpty/open_ctty.c create mode 100644 krb5-1-7/src/appl/libpty/open_slave.c create mode 100644 krb5-1-7/src/appl/libpty/pty-int.h create mode 100644 krb5-1-7/src/appl/libpty/pty_err.et create mode 100644 krb5-1-7/src/appl/libpty/pty_paranoia.c create mode 100644 krb5-1-7/src/appl/libpty/sane_hostname.c create mode 100644 krb5-1-7/src/appl/libpty/update_utmp.c create mode 100644 krb5-1-7/src/appl/libpty/update_wtmp.c create mode 100644 krb5-1-7/src/appl/libpty/vhangup.c create mode 100644 krb5-1-7/src/appl/libpty/void_assoc.c create mode 100644 krb5-1-7/src/appl/sample/Makefile.in create mode 100644 krb5-1-7/src/appl/sample/deps create mode 100644 krb5-1-7/src/appl/sample/sample.h create mode 100644 krb5-1-7/src/appl/sample/sclient/Makefile.in create mode 100644 krb5-1-7/src/appl/sample/sclient/deps create mode 100644 krb5-1-7/src/appl/sample/sclient/sclient.M create mode 100644 krb5-1-7/src/appl/sample/sclient/sclient.c create mode 100644 krb5-1-7/src/appl/sample/sserver/Makefile.in create mode 100644 krb5-1-7/src/appl/sample/sserver/deps create mode 100644 krb5-1-7/src/appl/sample/sserver/sserver.M create mode 100644 krb5-1-7/src/appl/sample/sserver/sserver.c create mode 100644 krb5-1-7/src/appl/simple/Makefile.in create mode 100644 krb5-1-7/src/appl/simple/client/Makefile.in create mode 100644 krb5-1-7/src/appl/simple/client/deps create mode 100644 krb5-1-7/src/appl/simple/client/sim_client.c create mode 100644 krb5-1-7/src/appl/simple/deps create mode 100644 krb5-1-7/src/appl/simple/server/Makefile.in create mode 100644 krb5-1-7/src/appl/simple/server/deps create mode 100644 krb5-1-7/src/appl/simple/server/sim_server.c create mode 100644 krb5-1-7/src/appl/simple/simple.h create mode 100644 krb5-1-7/src/appl/telnet/Config.generic create mode 100644 krb5-1-7/src/appl/telnet/Makefile.in create mode 100644 krb5-1-7/src/appl/telnet/README create mode 100644 krb5-1-7/src/appl/telnet/arpa/telnet.h create mode 100644 krb5-1-7/src/appl/telnet/configure.in create mode 100644 krb5-1-7/src/appl/telnet/deps create mode 100644 krb5-1-7/src/appl/telnet/kern.diff create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/Makefile.in create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/auth-proto.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/auth.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/auth.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/deps create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/enc-proto.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/enc_des.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/encrypt.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/encrypt.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/forward.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/genget.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/getent.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/getopt.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/gettytab.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/gettytab.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/herror.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/kerberos5.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/key-proto.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/krb5forw.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/mem.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/misc-proto.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/misc.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/misc.h create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/parsetos.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/setenv.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/setsid.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/spx.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strcasecmp.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strchr.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strdup.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strerror.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strftime.c create mode 100644 krb5-1-7/src/appl/telnet/libtelnet/strrchr.c create mode 100644 krb5-1-7/src/appl/telnet/stty.diff create mode 100644 krb5-1-7/src/appl/telnet/telnet.state create mode 100644 krb5-1-7/src/appl/telnet/telnet/Makefile.in create mode 100644 krb5-1-7/src/appl/telnet/telnet/authenc.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/commands.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/defines.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/deps create mode 100644 krb5-1-7/src/appl/telnet/telnet/externs.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/fdset.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/general.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/main.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/network.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/ring.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/ring.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/sys_bsd.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/telnet.0.ps create mode 100644 krb5-1-7/src/appl/telnet/telnet/telnet.0.txt create mode 100644 krb5-1-7/src/appl/telnet/telnet/telnet.1 create mode 100644 krb5-1-7/src/appl/telnet/telnet/telnet.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/terminal.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/tmac.doc create mode 100644 krb5-1-7/src/appl/telnet/telnet/tn3270.c create mode 100644 krb5-1-7/src/appl/telnet/telnet/types.h create mode 100644 krb5-1-7/src/appl/telnet/telnet/utilities.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/ISSUES create mode 100644 krb5-1-7/src/appl/telnet/telnetd/Makefile.in create mode 100644 krb5-1-7/src/appl/telnet/telnetd/authenc.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/defs.h create mode 100644 krb5-1-7/src/appl/telnet/telnetd/deps create mode 100644 krb5-1-7/src/appl/telnet/telnetd/ext.h create mode 100644 krb5-1-7/src/appl/telnet/telnetd/global.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/pathnames.h create mode 100644 krb5-1-7/src/appl/telnet/telnetd/slc.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/state.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/sys_term.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd-ktd.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd.0.ps create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd.0.txt create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd.8 create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/telnetd.h create mode 100644 krb5-1-7/src/appl/telnet/telnetd/termio-tn.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/termios-tn.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/termstat.c create mode 100644 krb5-1-7/src/appl/telnet/telnetd/utility.c create mode 100644 krb5-1-7/src/appl/user_user/Makefile.in create mode 100644 krb5-1-7/src/appl/user_user/client.c create mode 100644 krb5-1-7/src/appl/user_user/deps create mode 100644 krb5-1-7/src/appl/user_user/server.c create mode 100644 krb5-1-7/src/ccapi/Makefile.in create mode 100644 krb5-1-7/src/ccapi/common/Makefile.in create mode 100644 krb5-1-7/src/ccapi/common/cci_array_internal.c create mode 100644 krb5-1-7/src/ccapi/common/cci_array_internal.h create mode 100644 krb5-1-7/src/ccapi/common/cci_common.h create mode 100644 krb5-1-7/src/ccapi/common/cci_cred_union.c create mode 100644 krb5-1-7/src/ccapi/common/cci_cred_union.h create mode 100644 krb5-1-7/src/ccapi/common/cci_debugging.c create mode 100644 krb5-1-7/src/ccapi/common/cci_debugging.h create mode 100644 krb5-1-7/src/ccapi/common/cci_identifier.c create mode 100644 krb5-1-7/src/ccapi/common/cci_identifier.h create mode 100644 krb5-1-7/src/ccapi/common/cci_message.c create mode 100644 krb5-1-7/src/ccapi/common/cci_message.h create mode 100644 krb5-1-7/src/ccapi/common/cci_os_debugging.h create mode 100644 krb5-1-7/src/ccapi/common/cci_os_identifier.h create mode 100644 krb5-1-7/src/ccapi/common/cci_types.h create mode 100644 krb5-1-7/src/ccapi/common/mac/cci_os_debugging.c create mode 100644 krb5-1-7/src/ccapi/common/mac/cci_os_identifier.c create mode 100644 krb5-1-7/src/ccapi/common/unix/Makefile.in create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/autolock.hxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/ccutil.cxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/ccutil.def create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/ccutils.c create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/ccutils.h create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/init.cxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/init.hxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/name.h create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/opts.cxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/opts.hxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/secure.cxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/secure.hxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/util.cxx create mode 100644 krb5-1-7/src/ccapi/common/win/OldCC/util.h create mode 100644 krb5-1-7/src/ccapi/common/win/cci_os_debugging.c create mode 100644 krb5-1-7/src/ccapi/common/win/cci_os_identifier.c create mode 100644 krb5-1-7/src/ccapi/common/win/ccs_reply.Acf create mode 100644 krb5-1-7/src/ccapi/common/win/ccs_reply.Idl create mode 100644 krb5-1-7/src/ccapi/common/win/ccs_request.Acf create mode 100644 krb5-1-7/src/ccapi/common/win/ccs_request.idl create mode 100644 krb5-1-7/src/ccapi/common/win/tls.c create mode 100644 krb5-1-7/src/ccapi/common/win/tls.h create mode 100644 krb5-1-7/src/ccapi/common/win/win-utils.c create mode 100644 krb5-1-7/src/ccapi/common/win/win-utils.h create mode 100644 krb5-1-7/src/ccapi/doc/CCAPI-Windows-Design.html create mode 100644 krb5-1-7/src/ccapi/lib/Makefile.in create mode 100644 krb5-1-7/src/ccapi/lib/ccapi.exports create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ccache.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ccache.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_context.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_context.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_context_change_time.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_context_change_time.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_credentials.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_credentials.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_err.et create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ipc.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_ipc.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_os_ipc.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_string.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_string.h create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_v2.c create mode 100644 krb5-1-7/src/ccapi/lib/ccapi_v2.exports create mode 100644 krb5-1-7/src/ccapi/lib/mac/ccapi_os_ipc.c create mode 100644 krb5-1-7/src/ccapi/lib/mac/ccapi_vector.c create mode 100644 krb5-1-7/src/ccapi/lib/mac/ccapi_vector.exports create mode 100644 krb5-1-7/src/ccapi/lib/mac/ccapi_vector.h create mode 100644 krb5-1-7/src/ccapi/lib/unix/Makefile.in create mode 100644 krb5-1-7/src/ccapi/lib/win/Makefile.in create mode 100644 krb5-1-7/src/ccapi/lib/win/OldCC/ccapi.h create mode 100644 krb5-1-7/src/ccapi/lib/win/OldCC/client.cxx create mode 100644 krb5-1-7/src/ccapi/lib/win/OldCC/client.h create mode 100644 krb5-1-7/src/ccapi/lib/win/OldCC/rpc.cxx create mode 100644 krb5-1-7/src/ccapi/lib/win/WINCCAPI.sln create mode 100644 krb5-1-7/src/ccapi/lib/win/WINCCAPI.vcproj create mode 100644 krb5-1-7/src/ccapi/lib/win/ccapi_os_ipc.cxx create mode 100644 krb5-1-7/src/ccapi/lib/win/ccs_reply_proc.c create mode 100644 krb5-1-7/src/ccapi/lib/win/debug.exports create mode 100644 krb5-1-7/src/ccapi/lib/win/dllmain.cxx create mode 100644 krb5-1-7/src/ccapi/lib/win/dllmain.h create mode 100644 krb5-1-7/src/ccapi/server/Makefile.in create mode 100644 krb5-1-7/src/ccapi/server/ccs_array.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_array.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_cache_collection.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_cache_collection.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_callback.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_callback.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_ccache.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_ccache.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_ccache_iterator.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_ccache_iterator.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_client.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_client.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_common.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_credentials.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_credentials.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_credentials_iterator.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_credentials_iterator.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_list.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_list.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_list_internal.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_list_internal.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_lock.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_lock.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_lock_state.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_lock_state.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_os_notify.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_os_pipe.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_os_server.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_pipe.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_pipe.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_server.c create mode 100644 krb5-1-7/src/ccapi/server/ccs_server.h create mode 100644 krb5-1-7/src/ccapi/server/ccs_types.h create mode 100644 krb5-1-7/src/ccapi/server/mac/CCacheServerInfo.plist create mode 100644 krb5-1-7/src/ccapi/server/mac/ccs_os_notify.c create mode 100644 krb5-1-7/src/ccapi/server/mac/ccs_os_pipe.c create mode 100644 krb5-1-7/src/ccapi/server/mac/ccs_os_server.c create mode 100644 krb5-1-7/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist create mode 100644 krb5-1-7/src/ccapi/server/unix/Makefile.in create mode 100644 krb5-1-7/src/ccapi/server/win/Makefile.in create mode 100644 krb5-1-7/src/ccapi/server/win/Server.sln create mode 100644 krb5-1-7/src/ccapi/server/win/Server.vcproj create mode 100644 krb5-1-7/src/ccapi/server/win/WorkItem.cpp create mode 100644 krb5-1-7/src/ccapi/server/win/WorkQueue.cpp create mode 100644 krb5-1-7/src/ccapi/server/win/WorkQueue.h create mode 100644 krb5-1-7/src/ccapi/server/win/ccs_os_pipe.c create mode 100644 krb5-1-7/src/ccapi/server/win/ccs_os_server.cpp create mode 100644 krb5-1-7/src/ccapi/server/win/ccs_request_proc.c create mode 100644 krb5-1-7/src/ccapi/server/win/ccs_win_pipe.c create mode 100644 krb5-1-7/src/ccapi/server/win/ccs_win_pipe.h create mode 100644 krb5-1-7/src/ccapi/server/win/workitem.h create mode 100644 krb5-1-7/src/ccapi/test/Makefile.in create mode 100644 krb5-1-7/src/ccapi/test/Makefile.w32 create mode 100644 krb5-1-7/src/ccapi/test/Pingtest.sln create mode 100644 krb5-1-7/src/ccapi/test/main.c create mode 100644 krb5-1-7/src/ccapi/test/pingtest.c create mode 100644 krb5-1-7/src/ccapi/test/setlib.pl create mode 100644 krb5-1-7/src/ccapi/test/simple_lock_test.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_compare.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_destroy.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_change_time.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_credentials_version.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_last_default_time.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_name.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_get_principal.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_iterator_next.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_move.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_release.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_remove_credentials.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_set_default.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_set_principal.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_ccache_store_credentials.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_close.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_compare.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_create_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_create_default_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_create_new_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_get_change_time.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_get_default_ccache_name.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_new_ccache_iterator.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_open_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_open_default_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_context_release.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_create.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_credentials_iterator_next.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_destroy.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_get_NC_info.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_get_change_time.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_get_cred_version.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_get_name.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_get_principal.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_initialize.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_open.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_remove_cred.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_next.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_begin.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_next.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_set_principal.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_shutdown.c create mode 100644 krb5-1-7/src/ccapi/test/test_cc_store.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi.bat create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi.sh create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_ccache.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_ccache.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_check.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_check.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_constants.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_constants.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_context.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_context.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_globals.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_globals.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_iterators.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_iterators.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_log.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_log.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_util.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_util.h create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_v2.c create mode 100644 krb5-1-7/src/ccapi/test/test_ccapi_v2.h create mode 100644 krb5-1-7/src/ccapi/test/test_constants.c create mode 100644 krb5-1-7/src/clients/Makefile.in create mode 100644 krb5-1-7/src/clients/deps create mode 100644 krb5-1-7/src/clients/kcpytkt/Makefile.in create mode 100644 krb5-1-7/src/clients/kcpytkt/kcpytkt.M create mode 100644 krb5-1-7/src/clients/kcpytkt/kcpytkt.c create mode 100644 krb5-1-7/src/clients/kdeltkt/Makefile.in create mode 100644 krb5-1-7/src/clients/kdeltkt/kdeltkt.M create mode 100644 krb5-1-7/src/clients/kdeltkt/kdeltkt.c create mode 100644 krb5-1-7/src/clients/kdestroy/Makefile.in create mode 100644 krb5-1-7/src/clients/kdestroy/deps create mode 100644 krb5-1-7/src/clients/kdestroy/kdestroy.M create mode 100644 krb5-1-7/src/clients/kdestroy/kdestroy.c create mode 100644 krb5-1-7/src/clients/kinit/Makefile.in create mode 100644 krb5-1-7/src/clients/kinit/deps create mode 100644 krb5-1-7/src/clients/kinit/kinit.M create mode 100644 krb5-1-7/src/clients/kinit/kinit.c create mode 100644 krb5-1-7/src/clients/klist/Makefile.in create mode 100644 krb5-1-7/src/clients/klist/deps create mode 100644 krb5-1-7/src/clients/klist/klist.M create mode 100644 krb5-1-7/src/clients/klist/klist.c create mode 100644 krb5-1-7/src/clients/kpasswd/Makefile.in create mode 100644 krb5-1-7/src/clients/kpasswd/deps create mode 100644 krb5-1-7/src/clients/kpasswd/kpasswd.M create mode 100644 krb5-1-7/src/clients/kpasswd/kpasswd.c create mode 100644 krb5-1-7/src/clients/kpasswd/ksetpwd.c create mode 100644 krb5-1-7/src/clients/ksu/Makefile.in create mode 100644 krb5-1-7/src/clients/ksu/authorization.c create mode 100644 krb5-1-7/src/clients/ksu/ccache.c create mode 100644 krb5-1-7/src/clients/ksu/deps create mode 100644 krb5-1-7/src/clients/ksu/heuristic.c create mode 100644 krb5-1-7/src/clients/ksu/krb_auth_su.c create mode 100644 krb5-1-7/src/clients/ksu/ksu.M create mode 100644 krb5-1-7/src/clients/ksu/ksu.h create mode 100644 krb5-1-7/src/clients/ksu/main.c create mode 100644 krb5-1-7/src/clients/ksu/setenv.c create mode 100644 krb5-1-7/src/clients/ksu/xmalloc.c create mode 100644 krb5-1-7/src/clients/kvno/Makefile.in create mode 100644 krb5-1-7/src/clients/kvno/deps create mode 100644 krb5-1-7/src/clients/kvno/kvno.M create mode 100644 krb5-1-7/src/clients/kvno/kvno.c create mode 100644 krb5-1-7/src/config-files/Makefile.in create mode 100644 krb5-1-7/src/config-files/convert-config-files create mode 100644 krb5-1-7/src/config-files/deps create mode 100644 krb5-1-7/src/config-files/kdc.conf create mode 100644 krb5-1-7/src/config-files/kdc.conf.M create mode 100644 krb5-1-7/src/config-files/krb5.conf create mode 100644 krb5-1-7/src/config-files/krb5.conf.M create mode 100644 krb5-1-7/src/config-files/mech create mode 100644 krb5-1-7/src/config-files/services.append create mode 100644 krb5-1-7/src/config/ac-archive/README create mode 100644 krb5-1-7/src/config/ac-archive/acx_pthread.m4 create mode 100755 krb5-1-7/src/config/config.guess create mode 100755 krb5-1-7/src/config/config.sub create mode 100755 krb5-1-7/src/config/install-sh create mode 100644 krb5-1-7/src/config/lib.in create mode 100644 krb5-1-7/src/config/libnodeps.in create mode 100644 krb5-1-7/src/config/libnover.in create mode 100644 krb5-1-7/src/config/libobj.in create mode 100644 krb5-1-7/src/config/libpriv.in create mode 100755 krb5-1-7/src/config/mkinstalldirs create mode 100755 krb5-1-7/src/config/move-if-changed create mode 100644 krb5-1-7/src/config/post.in create mode 100644 krb5-1-7/src/config/pre.in create mode 100755 krb5-1-7/src/config/ren2long create mode 100644 krb5-1-7/src/config/ren2long.awk create mode 100644 krb5-1-7/src/config/rm.bat create mode 100644 krb5-1-7/src/config/shlib.conf create mode 100755 krb5-1-7/src/config/wconfig.pl create mode 100644 krb5-1-7/src/config/win-post.in create mode 100644 krb5-1-7/src/config/win-pre.in create mode 100644 krb5-1-7/src/config/winexclude.sed create mode 100644 krb5-1-7/src/configure.in create mode 100644 krb5-1-7/src/deps create mode 100644 krb5-1-7/src/gen-manpages/Makefile.in create mode 100644 krb5-1-7/src/gen-manpages/deps create mode 100644 krb5-1-7/src/gen-manpages/header.doc create mode 100644 krb5-1-7/src/gen-manpages/k5login.M create mode 100644 krb5-1-7/src/gen-manpages/kerberos.M create mode 100644 krb5-1-7/src/include/CredentialsCache.h create mode 100644 krb5-1-7/src/include/CredentialsCache2.h create mode 100644 krb5-1-7/src/include/Makefile.in create mode 100644 krb5-1-7/src/include/adm.h create mode 100644 krb5-1-7/src/include/adm_proto.h create mode 100644 krb5-1-7/src/include/cm.h create mode 100644 krb5-1-7/src/include/copyright.h create mode 100644 krb5-1-7/src/include/deps create mode 100644 krb5-1-7/src/include/fake-addrinfo.h create mode 100644 krb5-1-7/src/include/foreachaddr.h create mode 100644 krb5-1-7/src/include/gssapi.h create mode 100644 krb5-1-7/src/include/gssrpc/auth.h create mode 100644 krb5-1-7/src/include/gssrpc/auth_gss.h create mode 100644 krb5-1-7/src/include/gssrpc/auth_gssapi.h create mode 100644 krb5-1-7/src/include/gssrpc/auth_unix.h create mode 100644 krb5-1-7/src/include/gssrpc/clnt.h create mode 100644 krb5-1-7/src/include/gssrpc/netdb.h create mode 100644 krb5-1-7/src/include/gssrpc/pmap_clnt.h create mode 100644 krb5-1-7/src/include/gssrpc/pmap_prot.h create mode 100644 krb5-1-7/src/include/gssrpc/pmap_rmt.h create mode 100644 krb5-1-7/src/include/gssrpc/rename.h create mode 100644 krb5-1-7/src/include/gssrpc/rpc.h create mode 100644 krb5-1-7/src/include/gssrpc/rpc_msg.h create mode 100644 krb5-1-7/src/include/gssrpc/svc.h create mode 100644 krb5-1-7/src/include/gssrpc/svc_auth.h create mode 100644 krb5-1-7/src/include/gssrpc/types.hin create mode 100644 krb5-1-7/src/include/gssrpc/xdr.h create mode 100644 krb5-1-7/src/include/iprop.h create mode 100644 krb5-1-7/src/include/iprop_hdr.h create mode 100644 krb5-1-7/src/include/k5-buf.h create mode 100644 krb5-1-7/src/include/k5-err.h create mode 100644 krb5-1-7/src/include/k5-gmt_mktime.h create mode 100644 krb5-1-7/src/include/k5-int-pkinit.h create mode 100644 krb5-1-7/src/include/k5-int.h create mode 100644 krb5-1-7/src/include/k5-ipc_stream.h create mode 100644 krb5-1-7/src/include/k5-platform.h create mode 100644 krb5-1-7/src/include/k5-plugin.h create mode 100644 krb5-1-7/src/include/k5-thread.h create mode 100644 krb5-1-7/src/include/k5-unicode.h create mode 100644 krb5-1-7/src/include/k5-utf8.h create mode 100644 krb5-1-7/src/include/k5-util.h create mode 100644 krb5-1-7/src/include/kdb.h create mode 100644 krb5-1-7/src/include/kdb_ext.h create mode 100644 krb5-1-7/src/include/kdb_kt.h create mode 100644 krb5-1-7/src/include/kdb_log.h create mode 100644 krb5-1-7/src/include/kim/kim.h create mode 100644 krb5-1-7/src/include/kim/kim_ccache.h create mode 100644 krb5-1-7/src/include/kim/kim_credential.h create mode 100644 krb5-1-7/src/include/kim/kim_identity.h create mode 100644 krb5-1-7/src/include/kim/kim_library.h create mode 100644 krb5-1-7/src/include/kim/kim_options.h create mode 100644 krb5-1-7/src/include/kim/kim_preferences.h create mode 100644 krb5-1-7/src/include/kim/kim_selection_hints.h create mode 100644 krb5-1-7/src/include/kim/kim_string.h create mode 100644 krb5-1-7/src/include/kim/kim_types.h create mode 100644 krb5-1-7/src/include/kim/kim_ui_plugin.h create mode 100644 krb5-1-7/src/include/krb5.h create mode 100644 krb5-1-7/src/include/krb5/authdata_plugin.h create mode 100644 krb5-1-7/src/include/krb5/krb5.hin create mode 100644 krb5-1-7/src/include/krb5/locate_plugin.h create mode 100644 krb5-1-7/src/include/krb5/preauth_plugin.h create mode 100644 krb5-1-7/src/include/krb54proto.h create mode 100644 krb5-1-7/src/include/osconf.hin create mode 100644 krb5-1-7/src/include/pkinit_apple_utils.h create mode 100644 krb5-1-7/src/include/pkinit_asn1.h create mode 100644 krb5-1-7/src/include/pkinit_cert_store.h create mode 100644 krb5-1-7/src/include/pkinit_client.h create mode 100644 krb5-1-7/src/include/pkinit_cms.h create mode 100644 krb5-1-7/src/include/port-sockets.h create mode 100644 krb5-1-7/src/include/socket-utils.h create mode 100644 krb5-1-7/src/include/spnego-asn1.h create mode 100644 krb5-1-7/src/include/win-mac.h create mode 100644 krb5-1-7/src/kadmin/Makefile.in create mode 100644 krb5-1-7/src/kadmin/cli/Makefile.in create mode 100644 krb5-1-7/src/kadmin/cli/deps create mode 100644 krb5-1-7/src/kadmin/cli/getdate.y create mode 100644 krb5-1-7/src/kadmin/cli/k5srvutil.M create mode 100755 krb5-1-7/src/kadmin/cli/k5srvutil.sh create mode 100644 krb5-1-7/src/kadmin/cli/kadmin.M create mode 100644 krb5-1-7/src/kadmin/cli/kadmin.c create mode 100644 krb5-1-7/src/kadmin/cli/kadmin.h create mode 100644 krb5-1-7/src/kadmin/cli/kadmin.local.M create mode 100644 krb5-1-7/src/kadmin/cli/kadmin_ct.ct create mode 100644 krb5-1-7/src/kadmin/cli/keytab.c create mode 100644 krb5-1-7/src/kadmin/cli/keytab_local.c create mode 100644 krb5-1-7/src/kadmin/cli/ss_wrapper.c create mode 100644 krb5-1-7/src/kadmin/cli/strftime.c create mode 100644 krb5-1-7/src/kadmin/dbutil/Makefile.in create mode 100644 krb5-1-7/src/kadmin/dbutil/deps create mode 100644 krb5-1-7/src/kadmin/dbutil/dump.c create mode 100644 krb5-1-7/src/kadmin/dbutil/import_err.et create mode 100644 krb5-1-7/src/kadmin/dbutil/kadm5_create.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_create.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_destroy.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_mkey.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_stash.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_util.M create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_util.c create mode 100644 krb5-1-7/src/kadmin/dbutil/kdb5_util.h create mode 100644 krb5-1-7/src/kadmin/dbutil/nstrtok.h create mode 100644 krb5-1-7/src/kadmin/dbutil/ovload.c create mode 100644 krb5-1-7/src/kadmin/dbutil/string_table.c create mode 100644 krb5-1-7/src/kadmin/dbutil/string_table.h create mode 100644 krb5-1-7/src/kadmin/dbutil/strtok.c create mode 100644 krb5-1-7/src/kadmin/deps create mode 100644 krb5-1-7/src/kadmin/kdbkeys/Makefile.in create mode 100755 krb5-1-7/src/kadmin/kdbkeys/do-test.pl create mode 100644 krb5-1-7/src/kadmin/ktutil/Makefile.in create mode 100644 krb5-1-7/src/kadmin/ktutil/deps create mode 100644 krb5-1-7/src/kadmin/ktutil/ktutil.M create mode 100644 krb5-1-7/src/kadmin/ktutil/ktutil.c create mode 100644 krb5-1-7/src/kadmin/ktutil/ktutil.h create mode 100644 krb5-1-7/src/kadmin/ktutil/ktutil_ct.ct create mode 100644 krb5-1-7/src/kadmin/ktutil/ktutil_funcs.c create mode 100644 krb5-1-7/src/kadmin/passwd/Kpasswd create mode 100644 krb5-1-7/src/kadmin/passwd/Makefile.in create mode 100644 krb5-1-7/src/kadmin/passwd/deps create mode 100644 krb5-1-7/src/kadmin/passwd/kpasswd.M create mode 100644 krb5-1-7/src/kadmin/passwd/kpasswd.c create mode 100644 krb5-1-7/src/kadmin/passwd/kpasswd.h create mode 100644 krb5-1-7/src/kadmin/passwd/kpasswd_strings.et create mode 100644 krb5-1-7/src/kadmin/passwd/tty_kpasswd.c create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/Makefile.in create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/config/unix.exp create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/deps create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp create mode 100644 krb5-1-7/src/kadmin/passwd/unit-test/lib/helpers.exp create mode 100644 krb5-1-7/src/kadmin/passwd/xm_kpasswd.c create mode 100755 krb5-1-7/src/kadmin/scripts/inst-hdrs.sh create mode 100644 krb5-1-7/src/kadmin/server/Makefile.in create mode 100644 krb5-1-7/src/kadmin/server/deps create mode 100644 krb5-1-7/src/kadmin/server/ipropd_svc.c create mode 100644 krb5-1-7/src/kadmin/server/kadm_rpc_svc.c create mode 100644 krb5-1-7/src/kadmin/server/kadmind.M create mode 100644 krb5-1-7/src/kadmin/server/misc.c create mode 100644 krb5-1-7/src/kadmin/server/misc.h create mode 100644 krb5-1-7/src/kadmin/server/network.c create mode 100644 krb5-1-7/src/kadmin/server/ovsec_kadmd.c create mode 100644 krb5-1-7/src/kadmin/server/schpw.c create mode 100644 krb5-1-7/src/kadmin/server/server_glue_v1.c create mode 100644 krb5-1-7/src/kadmin/server/server_stubs.c create mode 100644 krb5-1-7/src/kadmin/testing/Makefile.in create mode 100644 krb5-1-7/src/kadmin/testing/deps create mode 100644 krb5-1-7/src/kadmin/testing/proto/kdc.conf.proto create mode 100644 krb5-1-7/src/kadmin/testing/proto/krb5.conf.proto create mode 100644 krb5-1-7/src/kadmin/testing/proto/ovsec_adm.dict create mode 100644 krb5-1-7/src/kadmin/testing/scripts/Makefile.in create mode 100755 krb5-1-7/src/kadmin/testing/scripts/compare_dump.plin create mode 100644 krb5-1-7/src/kadmin/testing/scripts/deps create mode 100755 krb5-1-7/src/kadmin/testing/scripts/env-setup.shin create mode 100755 krb5-1-7/src/kadmin/testing/scripts/find-make.sh create mode 100755 krb5-1-7/src/kadmin/testing/scripts/fixup-conf-files.plin create mode 100755 krb5-1-7/src/kadmin/testing/scripts/init_db create mode 100755 krb5-1-7/src/kadmin/testing/scripts/make-host-keytab.plin create mode 100755 krb5-1-7/src/kadmin/testing/scripts/qualname.plin create mode 100755 krb5-1-7/src/kadmin/testing/scripts/save_files.sh create mode 100755 krb5-1-7/src/kadmin/testing/scripts/simple_dump.plin create mode 100755 krb5-1-7/src/kadmin/testing/scripts/start_servers create mode 100755 krb5-1-7/src/kadmin/testing/scripts/start_servers_local create mode 100755 krb5-1-7/src/kadmin/testing/scripts/stop_servers create mode 100755 krb5-1-7/src/kadmin/testing/scripts/stop_servers_local create mode 100755 krb5-1-7/src/kadmin/testing/scripts/verify_xrunner_report.plin create mode 100644 krb5-1-7/src/kadmin/testing/tcl/util.t create mode 100644 krb5-1-7/src/kadmin/testing/util/Makefile.in create mode 100644 krb5-1-7/src/kadmin/testing/util/bsddb_dump.c create mode 100644 krb5-1-7/src/kadmin/testing/util/deps create mode 100644 krb5-1-7/src/kadmin/testing/util/tcl_kadm5.c create mode 100644 krb5-1-7/src/kadmin/testing/util/tcl_kadm5.h create mode 100644 krb5-1-7/src/kadmin/testing/util/tcl_krb5_hash.c create mode 100644 krb5-1-7/src/kadmin/testing/util/tcl_ovsec_kadm.c create mode 100644 krb5-1-7/src/kadmin/testing/util/tcl_ovsec_kadm_syntax create mode 100644 krb5-1-7/src/kadmin/testing/util/test.c create mode 100644 krb5-1-7/src/kdc/Makefile.in create mode 100644 krb5-1-7/src/kdc/deps create mode 100644 krb5-1-7/src/kdc/dispatch.c create mode 100644 krb5-1-7/src/kdc/do_as_req.c create mode 100644 krb5-1-7/src/kdc/do_tgs_req.c create mode 100644 krb5-1-7/src/kdc/extern.c create mode 100644 krb5-1-7/src/kdc/extern.h create mode 100644 krb5-1-7/src/kdc/fast_util.c create mode 100644 krb5-1-7/src/kdc/kdc5_err.et create mode 100644 krb5-1-7/src/kdc/kdc_authdata.c create mode 100644 krb5-1-7/src/kdc/kdc_preauth.c create mode 100644 krb5-1-7/src/kdc/kdc_util.c create mode 100644 krb5-1-7/src/kdc/kdc_util.h create mode 100644 krb5-1-7/src/kdc/krb5kdc.M create mode 100644 krb5-1-7/src/kdc/main.c create mode 100644 krb5-1-7/src/kdc/migration.doc create mode 100644 krb5-1-7/src/kdc/network.c create mode 100644 krb5-1-7/src/kdc/pkinit_apple_server.c create mode 100644 krb5-1-7/src/kdc/pkinit_server.h create mode 100644 krb5-1-7/src/kdc/policy.c create mode 100644 krb5-1-7/src/kdc/policy.h create mode 100644 krb5-1-7/src/kdc/replay.c create mode 100644 krb5-1-7/src/kdc/rtest.c create mode 100644 krb5-1-7/src/kdc/rtest.good create mode 100755 krb5-1-7/src/kdc/rtscript create mode 100644 krb5-1-7/src/kim/agent/mac/AuthenticationController.h create mode 100644 krb5-1-7/src/kim/agent/mac/AuthenticationController.m create mode 100644 krb5-1-7/src/kim/agent/mac/BadgedImageView.h create mode 100644 krb5-1-7/src/kim/agent/mac/BadgedImageView.m create mode 100644 krb5-1-7/src/kim/agent/mac/IPCClient.h create mode 100644 krb5-1-7/src/kim/agent/mac/IPCClient.m create mode 100644 krb5-1-7/src/kim/agent/mac/Identities.h create mode 100644 krb5-1-7/src/kim/agent/mac/Identities.m create mode 100644 krb5-1-7/src/kim/agent/mac/KIMUtilities.h create mode 100644 krb5-1-7/src/kim/agent/mac/KIMUtilities.m create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgent-Info.plist create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgentController.h create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgentController.m create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgentListener.h create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgentListener.m create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosAgentPrefix.pch create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosFormatters.h create mode 100644 krb5-1-7/src/kim/agent/mac/KerberosFormatters.m create mode 100644 krb5-1-7/src/kim/agent/mac/PopupButton.h create mode 100644 krb5-1-7/src/kim/agent/mac/PopupButton.m create mode 100644 krb5-1-7/src/kim/agent/mac/SelectIdentityController.h create mode 100644 krb5-1-7/src/kim/agent/mac/SelectIdentityController.m create mode 100644 krb5-1-7/src/kim/agent/mac/ServerDemux.h create mode 100644 krb5-1-7/src/kim/agent/mac/ServerDemux.m create mode 100644 krb5-1-7/src/kim/agent/mac/edu.mit.Kerberos.KerberosAgent.plist create mode 100644 krb5-1-7/src/kim/agent/mac/main.m create mode 100644 krb5-1-7/src/kim/agent/mac/resources/Add.tiff create mode 100644 krb5-1-7/src/kim/agent/mac/resources/Add_Pressed.tiff create mode 100644 krb5-1-7/src/kim/agent/mac/resources/English.lproj/Authentication.xib create mode 100644 krb5-1-7/src/kim/agent/mac/resources/English.lproj/AuthenticationController.strings create mode 100644 krb5-1-7/src/kim/agent/mac/resources/English.lproj/MainMenu.xib create mode 100644 krb5-1-7/src/kim/agent/mac/resources/English.lproj/SelectIdentity.strings create mode 100644 krb5-1-7/src/kim/agent/mac/resources/English.lproj/SelectIdentity.xib create mode 100644 krb5-1-7/src/kim/agent/mac/resources/Gear.tiff create mode 100644 krb5-1-7/src/kim/agent/mac/resources/KerberosAgent.icns create mode 100644 krb5-1-7/src/kim/agent/mac/resources/KerberosFormatters.strings create mode 100644 krb5-1-7/src/kim/agent/mac/resources/Remove.tiff create mode 100644 krb5-1-7/src/kim/agent/mac/resources/Remove_Pressed.tiff create mode 100644 krb5-1-7/src/kim/lib/kim-lite.exports create mode 100644 krb5-1-7/src/kim/lib/kim.exports create mode 100644 krb5-1-7/src/kim/lib/kim_ccache.c create mode 100644 krb5-1-7/src/kim/lib/kim_credential.c create mode 100644 krb5-1-7/src/kim/lib/kim_credential_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_debug.c create mode 100644 krb5-1-7/src/kim/lib/kim_debug_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_error_message.c create mode 100644 krb5-1-7/src/kim/lib/kim_error_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_errors.et create mode 100644 krb5-1-7/src/kim/lib/kim_identity.c create mode 100644 krb5-1-7/src/kim/lib/kim_identity_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_library.c create mode 100644 krb5-1-7/src/kim/lib/kim_library_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_options.c create mode 100644 krb5-1-7/src/kim/lib/kim_options_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_preferences.c create mode 100644 krb5-1-7/src/kim/lib/kim_preferences_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_selection_hints.c create mode 100644 krb5-1-7/src/kim/lib/kim_selection_hints_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_string.c create mode 100644 krb5-1-7/src/kim/lib/kim_string_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_ui.c create mode 100644 krb5-1-7/src/kim/lib/kim_ui_cli.c create mode 100644 krb5-1-7/src/kim/lib/kim_ui_cli_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_ui_gui_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_ui_plugin.c create mode 100644 krb5-1-7/src/kim/lib/kim_ui_plugin_private.h create mode 100644 krb5-1-7/src/kim/lib/kim_ui_private.h create mode 100644 krb5-1-7/src/kim/lib/mac/KerberosLogin.c create mode 100644 krb5-1-7/src/kim/lib/mac/KerberosLogin.exports create mode 100644 krb5-1-7/src/kim/lib/mac/KerberosLogin.h create mode 100755 krb5-1-7/src/kim/lib/mac/KerberosLoginErrors.et create mode 100644 krb5-1-7/src/kim/lib/mac/KerberosLoginPrivate.h create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_debug.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_identity.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_library.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_preferences.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_private.h create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_selection_hints.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_string.c create mode 100644 krb5-1-7/src/kim/lib/mac/kim_os_ui_gui.c create mode 100644 krb5-1-7/src/kim/test/main.c create mode 100644 krb5-1-7/src/kim/test/test_kim_common.c create mode 100644 krb5-1-7/src/kim/test/test_kim_common.h create mode 100644 krb5-1-7/src/kim/test/test_kim_identity.c create mode 100644 krb5-1-7/src/kim/test/test_kim_identity.h create mode 100644 krb5-1-7/src/kim/test/test_kim_preferences.c create mode 100644 krb5-1-7/src/kim/test/test_kim_preferences.h create mode 100644 krb5-1-7/src/kim/test/test_kim_selection_hints.c create mode 100644 krb5-1-7/src/kim/test/test_kim_selection_hints.h create mode 100644 krb5-1-7/src/kim/test/test_kll.c create mode 100644 krb5-1-7/src/kim/test/test_kll_terminal.c create mode 100644 krb5-1-7/src/kim/test/test_ui_plugin.c create mode 100644 krb5-1-7/src/krb5-config.M create mode 100755 krb5-1-7/src/krb5-config.in create mode 100644 krb5-1-7/src/lib/Makefile.in create mode 100644 krb5-1-7/src/lib/apputils/Makefile.in create mode 100644 krb5-1-7/src/lib/apputils/daemon.c create mode 100644 krb5-1-7/src/lib/apputils/deps create mode 100644 krb5-1-7/src/lib/apputils/dummy.c create mode 100644 krb5-1-7/src/lib/comerr32.def create mode 100644 krb5-1-7/src/lib/crypto/ISSUES create mode 100644 krb5-1-7/src/lib/crypto/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/aead.c create mode 100644 krb5-1-7/src/lib/crypto/aead.h create mode 100644 krb5-1-7/src/lib/crypto/aes/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/aes/aes-gen.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aes-test.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aes.h create mode 100644 krb5-1-7/src/lib/crypto/aes/aes.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/aes_s2k.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aes_s2k.h create mode 100644 krb5-1-7/src/lib/crypto/aes/aescpp.h create mode 100644 krb5-1-7/src/lib/crypto/aes/aescrypp.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aescrypt.asm create mode 100644 krb5-1-7/src/lib/crypto/aes/aescrypt.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aeskey.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aeskeypp.c create mode 100644 krb5-1-7/src/lib/crypto/aes/aesopt.h create mode 100644 krb5-1-7/src/lib/crypto/aes/aessrc.url create mode 100644 krb5-1-7/src/lib/crypto/aes/aestab.c create mode 100644 krb5-1-7/src/lib/crypto/aes/deps create mode 100644 krb5-1-7/src/lib/crypto/aes/expect-vk.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/expect-vt.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/Readme.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/cbc_d_m.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/cbc_e_m.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_d_m.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_e_m.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_iv.readme create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_iv.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_tbl.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_vk.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/ecb_vt.txt create mode 100644 krb5-1-7/src/lib/crypto/aes/test/katmct.pdf create mode 100644 krb5-1-7/src/lib/crypto/aes/uitypes.h create mode 100644 krb5-1-7/src/lib/crypto/aes/vb.txt create mode 100644 krb5-1-7/src/lib/crypto/arcfour/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/arcfour/arcfour-int.h create mode 100644 krb5-1-7/src/lib/crypto/arcfour/arcfour.c create mode 100644 krb5-1-7/src/lib/crypto/arcfour/arcfour.h create mode 100644 krb5-1-7/src/lib/crypto/arcfour/arcfour_aead.c create mode 100644 krb5-1-7/src/lib/crypto/arcfour/arcfour_s2k.c create mode 100644 krb5-1-7/src/lib/crypto/arcfour/deps create mode 100644 krb5-1-7/src/lib/crypto/block_size.c create mode 100644 krb5-1-7/src/lib/crypto/cf2.c create mode 100644 krb5-1-7/src/lib/crypto/checksum_length.c create mode 100644 krb5-1-7/src/lib/crypto/cksumtype_to_string.c create mode 100644 krb5-1-7/src/lib/crypto/cksumtypes.c create mode 100644 krb5-1-7/src/lib/crypto/cksumtypes.h create mode 100644 krb5-1-7/src/lib/crypto/coll_proof_cksum.c create mode 100644 krb5-1-7/src/lib/crypto/combine_keys.c create mode 100644 krb5-1-7/src/lib/crypto/crc32/CRC.pm create mode 100644 krb5-1-7/src/lib/crypto/crc32/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/crc32/Poly.pm create mode 100644 krb5-1-7/src/lib/crypto/crc32/crc-32.h create mode 100644 krb5-1-7/src/lib/crypto/crc32/crc.pl create mode 100644 krb5-1-7/src/lib/crypto/crc32/crc32.c create mode 100644 krb5-1-7/src/lib/crypto/crc32/deps create mode 100644 krb5-1-7/src/lib/crypto/crc32/t_crc.c create mode 100644 krb5-1-7/src/lib/crypto/crypto_length.c create mode 100644 krb5-1-7/src/lib/crypto/crypto_libinit.c create mode 100644 krb5-1-7/src/lib/crypto/decrypt.c create mode 100644 krb5-1-7/src/lib/crypto/decrypt_iov.c create mode 100644 krb5-1-7/src/lib/crypto/default_state.c create mode 100644 krb5-1-7/src/lib/crypto/deps create mode 100644 krb5-1-7/src/lib/crypto/des/ISSUES create mode 100644 krb5-1-7/src/lib/crypto/des/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/des/afsstring2key.c create mode 100644 krb5-1-7/src/lib/crypto/des/d3_aead.c create mode 100644 krb5-1-7/src/lib/crypto/des/d3_cbc.c create mode 100644 krb5-1-7/src/lib/crypto/des/d3_kysched.c create mode 100644 krb5-1-7/src/lib/crypto/des/deps create mode 100644 krb5-1-7/src/lib/crypto/des/des_int.h create mode 100644 krb5-1-7/src/lib/crypto/des/des_prf.c create mode 100644 krb5-1-7/src/lib/crypto/des/destest.c create mode 100644 krb5-1-7/src/lib/crypto/des/doc/libdes.doc create mode 100644 krb5-1-7/src/lib/crypto/des/f_aead.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_cbc.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_cksum.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_parity.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_sched.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_tables.c create mode 100644 krb5-1-7/src/lib/crypto/des/f_tables.h create mode 100644 krb5-1-7/src/lib/crypto/des/key_sched.c create mode 100644 krb5-1-7/src/lib/crypto/des/keytest.data create mode 100644 krb5-1-7/src/lib/crypto/des/string2key.c create mode 100644 krb5-1-7/src/lib/crypto/des/t_afss2k.c create mode 100644 krb5-1-7/src/lib/crypto/des/t_verify.c create mode 100644 krb5-1-7/src/lib/crypto/des/weak_key.c create mode 100644 krb5-1-7/src/lib/crypto/dk/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/dk/checksum.c create mode 100644 krb5-1-7/src/lib/crypto/dk/deps create mode 100644 krb5-1-7/src/lib/crypto/dk/derive.c create mode 100644 krb5-1-7/src/lib/crypto/dk/dk.h create mode 100644 krb5-1-7/src/lib/crypto/dk/dk_aead.c create mode 100644 krb5-1-7/src/lib/crypto/dk/dk_decrypt.c create mode 100644 krb5-1-7/src/lib/crypto/dk/dk_encrypt.c create mode 100644 krb5-1-7/src/lib/crypto/dk/dk_prf.c create mode 100644 krb5-1-7/src/lib/crypto/dk/stringtokey.c create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/aes.c create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/deps create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/des.c create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/des3.c create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/enc_provider.h create mode 100644 krb5-1-7/src/lib/crypto/enc_provider/rc4.c create mode 100644 krb5-1-7/src/lib/crypto/encrypt.c create mode 100644 krb5-1-7/src/lib/crypto/encrypt_iov.c create mode 100644 krb5-1-7/src/lib/crypto/encrypt_length.c create mode 100644 krb5-1-7/src/lib/crypto/enctype_compare.c create mode 100644 krb5-1-7/src/lib/crypto/enctype_to_string.c create mode 100644 krb5-1-7/src/lib/crypto/etypes.c create mode 100644 krb5-1-7/src/lib/crypto/etypes.h create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/deps create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/hash_crc32.c create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/hash_md4.c create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/hash_md5.c create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/hash_provider.h create mode 100644 krb5-1-7/src/lib/crypto/hash_provider/hash_sha1.c create mode 100644 krb5-1-7/src/lib/crypto/hmac.c create mode 100644 krb5-1-7/src/lib/crypto/keyblocks.c create mode 100644 krb5-1-7/src/lib/crypto/keyed_checksum_types.c create mode 100644 krb5-1-7/src/lib/crypto/keyed_cksum.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/deps create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/descbc.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/hmac_md5.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/k5_md4des.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/k5_md5des.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/keyhash_provider.h create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/md5_hmac.c create mode 100644 krb5-1-7/src/lib/crypto/keyhash_provider/t_cksum.c create mode 100644 krb5-1-7/src/lib/crypto/keylengths.c create mode 100644 krb5-1-7/src/lib/crypto/libk5crypto.exports create mode 100644 krb5-1-7/src/lib/crypto/make_checksum.c create mode 100644 krb5-1-7/src/lib/crypto/make_checksum_iov.c create mode 100644 krb5-1-7/src/lib/crypto/make_random_key.c create mode 100644 krb5-1-7/src/lib/crypto/mandatory_sumtype.c create mode 100644 krb5-1-7/src/lib/crypto/md4/ISSUES create mode 100644 krb5-1-7/src/lib/crypto/md4/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/md4/deps create mode 100644 krb5-1-7/src/lib/crypto/md4/md4.c create mode 100644 krb5-1-7/src/lib/crypto/md4/rsa-md4.h create mode 100644 krb5-1-7/src/lib/crypto/md5/ISSUES create mode 100644 krb5-1-7/src/lib/crypto/md5/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/md5/deps create mode 100644 krb5-1-7/src/lib/crypto/md5/md5.c create mode 100644 krb5-1-7/src/lib/crypto/md5/rsa-md5.h create mode 100644 krb5-1-7/src/lib/crypto/md5/t_cksum.c create mode 100644 krb5-1-7/src/lib/crypto/md5/t_mddriver.c create mode 100644 krb5-1-7/src/lib/crypto/nfold.c create mode 100644 krb5-1-7/src/lib/crypto/old/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/old/deps create mode 100644 krb5-1-7/src/lib/crypto/old/des_stringtokey.c create mode 100644 krb5-1-7/src/lib/crypto/old/old.h create mode 100644 krb5-1-7/src/lib/crypto/old/old_decrypt.c create mode 100644 krb5-1-7/src/lib/crypto/old/old_encrypt.c create mode 100644 krb5-1-7/src/lib/crypto/old_api_glue.c create mode 100644 krb5-1-7/src/lib/crypto/pbkdf2.c create mode 100644 krb5-1-7/src/lib/crypto/prf.c create mode 100644 krb5-1-7/src/lib/crypto/prng.c create mode 100644 krb5-1-7/src/lib/crypto/random_to_key.c create mode 100644 krb5-1-7/src/lib/crypto/raw/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/raw/deps create mode 100644 krb5-1-7/src/lib/crypto/raw/raw.h create mode 100644 krb5-1-7/src/lib/crypto/raw/raw_aead.c create mode 100644 krb5-1-7/src/lib/crypto/raw/raw_decrypt.c create mode 100644 krb5-1-7/src/lib/crypto/raw/raw_encrypt.c create mode 100644 krb5-1-7/src/lib/crypto/sha1/ISSUES create mode 100644 krb5-1-7/src/lib/crypto/sha1/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/sha1/deps create mode 100644 krb5-1-7/src/lib/crypto/sha1/shs.c create mode 100644 krb5-1-7/src/lib/crypto/sha1/shs.h create mode 100644 krb5-1-7/src/lib/crypto/sha1/t_shs.c create mode 100644 krb5-1-7/src/lib/crypto/sha1/t_shs3.c create mode 100644 krb5-1-7/src/lib/crypto/state.c create mode 100644 krb5-1-7/src/lib/crypto/string_to_cksumtype.c create mode 100644 krb5-1-7/src/lib/crypto/string_to_enctype.c create mode 100644 krb5-1-7/src/lib/crypto/string_to_key.c create mode 100644 krb5-1-7/src/lib/crypto/t_cf2.c create mode 100644 krb5-1-7/src/lib/crypto/t_cf2.comments create mode 100644 krb5-1-7/src/lib/crypto/t_cf2.expected create mode 100644 krb5-1-7/src/lib/crypto/t_cf2.in create mode 100644 krb5-1-7/src/lib/crypto/t_cts.c create mode 100644 krb5-1-7/src/lib/crypto/t_encrypt.c create mode 100644 krb5-1-7/src/lib/crypto/t_hmac.c create mode 100644 krb5-1-7/src/lib/crypto/t_nfold.c create mode 100644 krb5-1-7/src/lib/crypto/t_pkcs5.c create mode 100644 krb5-1-7/src/lib/crypto/t_prf.c create mode 100644 krb5-1-7/src/lib/crypto/t_prf.comments create mode 100644 krb5-1-7/src/lib/crypto/t_prf.expected create mode 100644 krb5-1-7/src/lib/crypto/t_prf.in create mode 100644 krb5-1-7/src/lib/crypto/t_prng.c create mode 100644 krb5-1-7/src/lib/crypto/t_prng.comments create mode 100644 krb5-1-7/src/lib/crypto/t_prng.expected create mode 100644 krb5-1-7/src/lib/crypto/t_prng.reseedtest create mode 100644 krb5-1-7/src/lib/crypto/t_prng.reseedtest-comments create mode 100644 krb5-1-7/src/lib/crypto/t_prng.reseedtest-expected create mode 100644 krb5-1-7/src/lib/crypto/t_prng.seed create mode 100644 krb5-1-7/src/lib/crypto/t_short.c create mode 100644 krb5-1-7/src/lib/crypto/valid_cksumtype.c create mode 100644 krb5-1-7/src/lib/crypto/valid_enctype.c create mode 100644 krb5-1-7/src/lib/crypto/vectors.c create mode 100644 krb5-1-7/src/lib/crypto/verify_checksum.c create mode 100644 krb5-1-7/src/lib/crypto/verify_checksum_iov.c create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ASSUMPTIONS create mode 100644 krb5-1-7/src/lib/crypto/yarrow/LICENSE create mode 100644 krb5-1-7/src/lib/crypto/yarrow/Makefile.in create mode 100644 krb5-1-7/src/lib/crypto/yarrow/README create mode 100644 krb5-1-7/src/lib/crypto/yarrow/TODO create mode 100644 krb5-1-7/src/lib/crypto/yarrow/deps create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yarrow.c create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yarrow.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yarrow.man create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yarrow.pod create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ycipher.c create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ycipher.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yexcep.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/yhash.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ylock.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ystate.h create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ytest.c create mode 100644 krb5-1-7/src/lib/crypto/yarrow/ytypes.h create mode 100644 krb5-1-7/src/lib/deps create mode 100644 krb5-1-7/src/lib/glue4.c create mode 100644 krb5-1-7/src/lib/gssapi/LICENSE create mode 100644 krb5-1-7/src/lib/gssapi/Makefile.in create mode 100644 krb5-1-7/src/lib/gssapi/README_SAMPLE_APP create mode 100644 krb5-1-7/src/lib/gssapi/deps create mode 100644 krb5-1-7/src/lib/gssapi/generic/Makefile.in create mode 100644 krb5-1-7/src/lib/gssapi/generic/deps create mode 100644 krb5-1-7/src/lib/gssapi/generic/disp_com_err_status.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/disp_major_status.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapi.hin create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapiP_generic.h create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapi_err_generic.et create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapi_ext.h create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapi_generic.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/gssapi_generic.h create mode 100644 krb5-1-7/src/lib/gssapi/generic/maptest.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/oid_ops.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/rel_buffer.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/rel_oid_set.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_buffer.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_buffer_set.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_canonhost.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_errmap.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_localhost.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_ordering.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_set.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_token.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/util_validate.c create mode 100644 krb5-1-7/src/lib/gssapi/generic/utl_nohash_validate.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/3des.txt create mode 100644 krb5-1-7/src/lib/gssapi/krb5/Makefile.in create mode 100644 krb5-1-7/src/lib/gssapi/krb5/accept_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/acquire_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/add_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/canon_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/compare_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/context_time.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/copy_ccache.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/delete_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/deps create mode 100644 krb5-1-7/src/lib/gssapi/krb5/disp_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/disp_status.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/duplicate_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/export_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/export_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/get_tkt_flags.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/gssapiP_krb5.h create mode 100644 krb5-1-7/src/lib/gssapi/krb5/gssapi_err_krb5.et create mode 100644 krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.hin create mode 100644 krb5-1-7/src/lib/gssapi/krb5/import_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/import_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/indicate_mechs.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/init_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/inq_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/inq_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/inq_names.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5seal.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5sealiov.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5sealv3.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5sealv3iov.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5unseal.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/k5unsealiov.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/krb5_gss_glue.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/lucid_context.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/process_context_token.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/rel_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/rel_name.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/rel_oid.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/seal.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/ser_sctx.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/set_allowable_enctypes.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/set_ccache.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/sign.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/unseal.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/util_cksum.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/util_crypt.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/util_seed.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/util_seqnum.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/val_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/verify.c create mode 100644 krb5-1-7/src/lib/gssapi/krb5/wrap_size_limit.c create mode 100644 krb5-1-7/src/lib/gssapi/libgssapi_krb5.exports create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/Makefile.in create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/deps create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_accept_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_acquire_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_buffer_set.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_canon_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_compare_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_complete_auth_token.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_context_time.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_delete_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_dsp_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_dsp_status.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_dup_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_exp_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_export_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_glue.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_imp_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_imp_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_init_sec_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_initialize.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_inq_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_inq_context_oid.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred_oid.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_inq_names.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_mech_invoke.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_mechname.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_oid_ops.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_process_context.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_rel_buffer.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_rel_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_rel_name.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_rel_oid_set.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_seal.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_set_context_option.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_set_cred_option.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_sign.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_store_cred.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_unseal.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_aead.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_iov.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_userok.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_verify.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_wrap_aead.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/g_wrap_iov.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/gssd_pname_to_uid.c create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/mechglue.h create mode 100644 krb5-1-7/src/lib/gssapi/mechglue/mglueP.h create mode 100644 krb5-1-7/src/lib/gssapi/spnego/Makefile.in create mode 100644 krb5-1-7/src/lib/gssapi/spnego/deps create mode 100644 krb5-1-7/src/lib/gssapi/spnego/gssapiP_spnego.h create mode 100644 krb5-1-7/src/lib/gssapi/spnego/mech_spnego.exports create mode 100644 krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c create mode 100644 krb5-1-7/src/lib/gssapi32.def create mode 100644 krb5-1-7/src/lib/kadm5/Makefile.in create mode 100644 krb5-1-7/src/lib/kadm5/adb.h create mode 100644 krb5-1-7/src/lib/kadm5/admin.h create mode 100644 krb5-1-7/src/lib/kadm5/admin_internal.h create mode 100644 krb5-1-7/src/lib/kadm5/admin_xdr.h create mode 100644 krb5-1-7/src/lib/kadm5/alt_prof.c create mode 100644 krb5-1-7/src/lib/kadm5/chpass_util.c create mode 100644 krb5-1-7/src/lib/kadm5/chpass_util_strings.et create mode 100644 krb5-1-7/src/lib/kadm5/clnt/Makefile.in create mode 100644 krb5-1-7/src/lib/kadm5/clnt/client_handle.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/client_init.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/client_internal.h create mode 100644 krb5-1-7/src/lib/kadm5/clnt/client_principal.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/client_rpc.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/clnt_chpass_util.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/clnt_policy.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/clnt_privs.c create mode 100644 krb5-1-7/src/lib/kadm5/clnt/deps create mode 100644 krb5-1-7/src/lib/kadm5/clnt/libkadm5clnt.exports create mode 100644 krb5-1-7/src/lib/kadm5/deps create mode 100644 krb5-1-7/src/lib/kadm5/kadm_err.et create mode 100644 krb5-1-7/src/lib/kadm5/kadm_rpc.h create mode 100644 krb5-1-7/src/lib/kadm5/kadm_rpc_xdr.c create mode 100644 krb5-1-7/src/lib/kadm5/logger.c create mode 100644 krb5-1-7/src/lib/kadm5/misc_free.c create mode 100644 krb5-1-7/src/lib/kadm5/ovsec_glue.c create mode 100644 krb5-1-7/src/lib/kadm5/server_internal.h create mode 100644 krb5-1-7/src/lib/kadm5/srv/Makefile.in create mode 100644 krb5-1-7/src/lib/kadm5/srv/adb_xdr.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/deps create mode 100644 krb5-1-7/src/lib/kadm5/srv/libkadm5srv.exports create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_acl.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_acl.h create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_dict.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_handle.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_init.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_kdb.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/server_misc.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/svr_chpass_util.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/svr_iters.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/svr_misc_free.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/svr_policy.c create mode 100644 krb5-1-7/src/lib/kadm5/srv/svr_principal.c create mode 100644 krb5-1-7/src/lib/kadm5/str_conv.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/Makefile.in create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/README.new-tests create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/chpass-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/crte-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/crte-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/destroy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/dlte-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/dlte-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/get-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/get-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/init.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/mod-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/mod-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/randkey-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.0/rename-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.1/lock.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/chpass-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/destroy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/dlte-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/dlte-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/get-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/get-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/init-v2.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/init.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-policy.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/api.2/randkey-principal.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/config/unix.exp create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/deps create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/destroy-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/diff-files/destroy-1 create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/diff-files/no-diffs create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/handle-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/init-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/iter-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/lib/lib.t create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/lock-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/randkey-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/setkey-test.c create mode 100644 krb5-1-7/src/lib/kadm5/unit-test/site.exp create mode 100644 krb5-1-7/src/lib/kdb/Makefile.in create mode 100644 krb5-1-7/src/lib/kdb/adb_err.et create mode 100644 krb5-1-7/src/lib/kdb/decrypt_key.c create mode 100644 krb5-1-7/src/lib/kdb/deps create mode 100644 krb5-1-7/src/lib/kdb/encrypt_key.c create mode 100644 krb5-1-7/src/lib/kdb/iprop.x create mode 100644 krb5-1-7/src/lib/kdb/iprop_xdr.c create mode 100644 krb5-1-7/src/lib/kdb/kdb5.c create mode 100644 krb5-1-7/src/lib/kdb/kdb5.h create mode 100644 krb5-1-7/src/lib/kdb/kdb5int.h create mode 100644 krb5-1-7/src/lib/kdb/kdb_convert.c create mode 100644 krb5-1-7/src/lib/kdb/kdb_cpw.c create mode 100644 krb5-1-7/src/lib/kdb/kdb_default.c create mode 100644 krb5-1-7/src/lib/kdb/kdb_log.c create mode 100644 krb5-1-7/src/lib/kdb/keytab.c create mode 100644 krb5-1-7/src/lib/kdb/libkdb5.exports create mode 100644 krb5-1-7/src/lib/krb4_32.def create mode 100644 krb5-1-7/src/lib/krb5.rc create mode 100644 krb5-1-7/src/lib/krb5/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/asn.1/KRB5-asn.py create mode 100644 krb5-1-7/src/lib/krb5/asn.1/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/asn.1/TODO.asn1 create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_decode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_decode.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_encode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_encode.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_get.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_get.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_make.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_make.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_misc.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1_misc.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1buf.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1buf.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/asn1glue.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/deps create mode 100644 krb5-1-7/src/lib/krb5/asn.1/krb5_decode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/krb5_encode.c create mode 100644 krb5-1-7/src/lib/krb5/asn.1/krbasn1.h create mode 100644 krb5-1-7/src/lib/krb5/asn.1/ldap_key_seq.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc-int.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc_file.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc_keyring.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc_memory.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc_mslsa.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cc_retr.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccbase.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cccopy.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/cccursor.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccdefault.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccdefops.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/ccfns.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/deps create mode 100644 krb5-1-7/src/lib/krb5/ccache/fcc.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/scc.h create mode 100644 krb5-1-7/src/lib/krb5/ccache/ser_cc.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/t_cc.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/t_cccursor.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/t_memory.c create mode 100644 krb5-1-7/src/lib/krb5/ccache/t_stdio.c create mode 100644 krb5-1-7/src/lib/krb5/deps create mode 100644 krb5-1-7/src/lib/krb5/error_tables/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/error_tables/asn1_err.et create mode 100644 krb5-1-7/src/lib/krb5/error_tables/deps create mode 100644 krb5-1-7/src/lib/krb5/error_tables/init_ets.c create mode 100644 krb5-1-7/src/lib/krb5/error_tables/kdb5_err.et create mode 100644 krb5-1-7/src/lib/krb5/error_tables/krb524_err.et create mode 100644 krb5-1-7/src/lib/krb5/error_tables/krb5_err.et create mode 100644 krb5-1-7/src/lib/krb5/error_tables/kv5m_err.et create mode 100644 krb5-1-7/src/lib/krb5/keytab/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/keytab/deps create mode 100644 krb5-1-7/src/lib/krb5/keytab/kt-int.h create mode 100644 krb5-1-7/src/lib/krb5/keytab/kt_file.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/kt_memory.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/kt_srvtab.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktadd.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktbase.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktdefault.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktfns.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktfr_entry.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/ktremove.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/read_servi.c create mode 100644 krb5-1-7/src/lib/krb5/keytab/t_keytab.c create mode 100644 krb5-1-7/src/lib/krb5/krb/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/krb/addr_comp.c create mode 100644 krb5-1-7/src/lib/krb5/krb/addr_order.c create mode 100644 krb5-1-7/src/lib/krb5/krb/addr_srch.c create mode 100644 krb5-1-7/src/lib/krb5/krb/appdefault.c create mode 100644 krb5-1-7/src/lib/krb5/krb/auth_con.c create mode 100644 krb5-1-7/src/lib/krb5/krb/auth_con.h create mode 100644 krb5-1-7/src/lib/krb5/krb/bld_pr_ext.c create mode 100644 krb5-1-7/src/lib/krb5/krb/bld_princ.c create mode 100644 krb5-1-7/src/lib/krb5/krb/brand.c create mode 100644 krb5-1-7/src/lib/krb5/krb/chk_trans.c create mode 100644 krb5-1-7/src/lib/krb5/krb/chpw.c create mode 100644 krb5-1-7/src/lib/krb5/krb/cleanup.h create mode 100644 krb5-1-7/src/lib/krb5/krb/conv_creds.c create mode 100644 krb5-1-7/src/lib/krb5/krb/conv_princ.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_addrs.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_athctr.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_auth.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_cksum.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_creds.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_data.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_key.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_princ.c create mode 100644 krb5-1-7/src/lib/krb5/krb/copy_tick.c create mode 100644 krb5-1-7/src/lib/krb5/krb/cp_key_cnt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/decode_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/krb/decrypt_tk.c create mode 100644 krb5-1-7/src/lib/krb5/krb/deltat.c create mode 100644 krb5-1-7/src/lib/krb5/krb/deps create mode 100644 krb5-1-7/src/lib/krb5/krb/enc_helper.c create mode 100644 krb5-1-7/src/lib/krb5/krb/encode_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/krb/encrypt_tk.c create mode 100644 krb5-1-7/src/lib/krb5/krb/fast.c create mode 100644 krb5-1-7/src/lib/krb5/krb/fast.h create mode 100644 krb5-1-7/src/lib/krb5/krb/free_rtree.c create mode 100644 krb5-1-7/src/lib/krb5/krb/fwd_tgt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gc_frm_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gc_via_tkt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gen_seqnum.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gen_subkey.c create mode 100644 krb5-1-7/src/lib/krb5/krb/get_creds.c create mode 100644 krb5-1-7/src/lib/krb5/krb/get_in_tkt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gic_keytab.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gic_opt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/gic_pwd.c create mode 100644 krb5-1-7/src/lib/krb5/krb/in_tkt_sky.c create mode 100644 krb5-1-7/src/lib/krb5/krb/init_ctx.c create mode 100644 krb5-1-7/src/lib/krb5/krb/init_keyblock.c create mode 100644 krb5-1-7/src/lib/krb5/krb/int-proto.h create mode 100644 krb5-1-7/src/lib/krb5/krb/kdc_rep_dc.c create mode 100644 krb5-1-7/src/lib/krb5/krb/kerrs.c create mode 100644 krb5-1-7/src/lib/krb5/krb/kfree.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_cred.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_error.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_priv.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_rep.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_req.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_req_ext.c create mode 100644 krb5-1-7/src/lib/krb5/krb/mk_safe.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pac.c create mode 100644 krb5-1-7/src/lib/krb5/krb/parse.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pkinit_apple_asn1.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pkinit_apple_cert_store.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pkinit_apple_client.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pkinit_apple_cms.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pkinit_apple_utils.c create mode 100644 krb5-1-7/src/lib/krb5/krb/pr_to_salt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/preauth.c create mode 100644 krb5-1-7/src/lib/krb5/krb/preauth2.c create mode 100644 krb5-1-7/src/lib/krb5/krb/princ_comp.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_cred.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_error.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_priv.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_rep.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_req.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_req_dec.c create mode 100644 krb5-1-7/src/lib/krb5/krb/rd_safe.c create mode 100644 krb5-1-7/src/lib/krb5/krb/recvauth.c create mode 100644 krb5-1-7/src/lib/krb5/krb/send_tgs.c create mode 100644 krb5-1-7/src/lib/krb5/krb/sendauth.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_actx.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_adata.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_addr.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_auth.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_cksum.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_ctx.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_eblk.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_key.c create mode 100644 krb5-1-7/src/lib/krb5/krb/ser_princ.c create mode 100644 krb5-1-7/src/lib/krb5/krb/serialize.c create mode 100644 krb5-1-7/src/lib/krb5/krb/set_realm.c create mode 100644 krb5-1-7/src/lib/krb5/krb/srv_dec_tkt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/srv_rcache.c create mode 100644 krb5-1-7/src/lib/krb5/krb/str_conv.c create mode 100644 krb5-1-7/src/lib/krb5/krb/strftime.c create mode 100644 krb5-1-7/src/lib/krb5/krb/strptime.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_ad_fx_armor.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_authdata.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_deltat.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_expand.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_kerb.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_krb5.conf create mode 100644 krb5-1-7/src/lib/krb5/krb/t_pac.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_princ.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_ref_kerb.out create mode 100644 krb5-1-7/src/lib/krb5/krb/t_ser.c create mode 100644 krb5-1-7/src/lib/krb5/krb/t_walk_rtree.c create mode 100644 krb5-1-7/src/lib/krb5/krb/tgtname.c create mode 100755 krb5-1-7/src/lib/krb5/krb/transit-tests create mode 100644 krb5-1-7/src/lib/krb5/krb/unparse.c create mode 100644 krb5-1-7/src/lib/krb5/krb/valid_times.c create mode 100644 krb5-1-7/src/lib/krb5/krb/vfy_increds.c create mode 100644 krb5-1-7/src/lib/krb5/krb/vic_opt.c create mode 100644 krb5-1-7/src/lib/krb5/krb/walk_rtree.c create mode 100644 krb5-1-7/src/lib/krb5/krb/walktree-tests create mode 100644 krb5-1-7/src/lib/krb5/krb/x-deltat.y create mode 100644 krb5-1-7/src/lib/krb5/krb5_libinit.c create mode 100644 krb5-1-7/src/lib/krb5/krb5_libinit.h create mode 100644 krb5-1-7/src/lib/krb5/libkrb5.exports create mode 100644 krb5-1-7/src/lib/krb5/os/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/os/accessor.c create mode 100644 krb5-1-7/src/lib/krb5/os/an_to_ln.c create mode 100644 krb5-1-7/src/lib/krb5/os/c_ustime.c create mode 100644 krb5-1-7/src/lib/krb5/os/ccdefname.c create mode 100644 krb5-1-7/src/lib/krb5/os/changepw.c create mode 100644 krb5-1-7/src/lib/krb5/os/def_realm.c create mode 100644 krb5-1-7/src/lib/krb5/os/deps create mode 100644 krb5-1-7/src/lib/krb5/os/dnsglue.c create mode 100644 krb5-1-7/src/lib/krb5/os/dnsglue.h create mode 100644 krb5-1-7/src/lib/krb5/os/dnssrv.c create mode 100644 krb5-1-7/src/lib/krb5/os/free_hstrl.c create mode 100644 krb5-1-7/src/lib/krb5/os/free_krbhs.c create mode 100644 krb5-1-7/src/lib/krb5/os/full_ipadr.c create mode 100644 krb5-1-7/src/lib/krb5/os/gen_port.c create mode 100644 krb5-1-7/src/lib/krb5/os/gen_rname.c create mode 100644 krb5-1-7/src/lib/krb5/os/genaddrs.c create mode 100644 krb5-1-7/src/lib/krb5/os/get_krbhst.c create mode 100644 krb5-1-7/src/lib/krb5/os/hostaddr.c create mode 100644 krb5-1-7/src/lib/krb5/os/hst_realm.c create mode 100644 krb5-1-7/src/lib/krb5/os/init_os_ctx.c create mode 100644 krb5-1-7/src/lib/krb5/os/krbfileio.c create mode 100644 krb5-1-7/src/lib/krb5/os/ktdefname.c create mode 100644 krb5-1-7/src/lib/krb5/os/kuserok.c create mode 100644 krb5-1-7/src/lib/krb5/os/localaddr.c create mode 100644 krb5-1-7/src/lib/krb5/os/locate_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/os/lock_file.c create mode 100644 krb5-1-7/src/lib/krb5/os/mk_faddr.c create mode 100644 krb5-1-7/src/lib/krb5/os/net_read.c create mode 100644 krb5-1-7/src/lib/krb5/os/net_write.c create mode 100644 krb5-1-7/src/lib/krb5/os/os-proto.h create mode 100644 krb5-1-7/src/lib/krb5/os/osconfig.c create mode 100644 krb5-1-7/src/lib/krb5/os/port2ip.c create mode 100644 krb5-1-7/src/lib/krb5/os/prompter.c create mode 100644 krb5-1-7/src/lib/krb5/os/promptusr.c create mode 100644 krb5-1-7/src/lib/krb5/os/read_msg.c create mode 100644 krb5-1-7/src/lib/krb5/os/read_pwd.c create mode 100644 krb5-1-7/src/lib/krb5/os/realm_dom.c create mode 100644 krb5-1-7/src/lib/krb5/os/realm_iter.c create mode 100644 krb5-1-7/src/lib/krb5/os/ref_std_conf.out create mode 100644 krb5-1-7/src/lib/krb5/os/sendto_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/os/sn2princ.c create mode 100644 krb5-1-7/src/lib/krb5/os/t_an_to_ln.c create mode 100644 krb5-1-7/src/lib/krb5/os/t_gifconf.c create mode 100644 krb5-1-7/src/lib/krb5/os/t_locate_kdc.c create mode 100644 krb5-1-7/src/lib/krb5/os/t_realm_iter.c create mode 100644 krb5-1-7/src/lib/krb5/os/t_std_conf.c create mode 100644 krb5-1-7/src/lib/krb5/os/td_krb5.conf create mode 100644 krb5-1-7/src/lib/krb5/os/thread_safe.c create mode 100644 krb5-1-7/src/lib/krb5/os/timeofday.c create mode 100644 krb5-1-7/src/lib/krb5/os/toffset.c create mode 100644 krb5-1-7/src/lib/krb5/os/unlck_file.c create mode 100644 krb5-1-7/src/lib/krb5/os/ustime.c create mode 100644 krb5-1-7/src/lib/krb5/os/write_msg.c create mode 100644 krb5-1-7/src/lib/krb5/posix/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/posix/syslog.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/rcache/README create mode 100644 krb5-1-7/src/lib/krb5/rcache/RELEASE create mode 100644 krb5-1-7/src/lib/krb5/rcache/deps create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc-int.h create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_base.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_base.h create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_conv.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_dfl.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_dfl.h create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_io.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_io.h create mode 100644 krb5-1-7/src/lib/krb5/rcache/rc_none.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rcdef.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/rcfns.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/ser_rc.c create mode 100644 krb5-1-7/src/lib/krb5/rcache/t_replay.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/CompositionExclusions.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/Makefile.in create mode 100644 krb5-1-7/src/lib/krb5/unicode/UCD-Terms create mode 100644 krb5-1-7/src/lib/krb5/unicode/UnicodeData.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/deps create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/MUTTUCData.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/README create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/api.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/bidiapi.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/format.txt create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucdata.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucdata.h create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucdata.man create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucgendat.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucpgba.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucpgba.h create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/ucpgba.man create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucdata/uctable.h create mode 100644 krb5-1-7/src/lib/krb5/unicode/ucstr.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/ure/README create mode 100644 krb5-1-7/src/lib/krb5/unicode/ure/ure.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/ure/ure.h create mode 100644 krb5-1-7/src/lib/krb5/unicode/ure/urestubs.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/utbm/README create mode 100644 krb5-1-7/src/lib/krb5/unicode/utbm/utbm.c create mode 100644 krb5-1-7/src/lib/krb5/unicode/utbm/utbm.h create mode 100644 krb5-1-7/src/lib/krb5/unicode/utbm/utbmstub.c create mode 100644 krb5-1-7/src/lib/krb5_32.def create mode 100644 krb5-1-7/src/lib/rpc/Makefile.in create mode 100644 krb5-1-7/src/lib/rpc/auth_gss.c create mode 100644 krb5-1-7/src/lib/rpc/auth_gssapi.c create mode 100644 krb5-1-7/src/lib/rpc/auth_gssapi_misc.c create mode 100644 krb5-1-7/src/lib/rpc/auth_none.c create mode 100644 krb5-1-7/src/lib/rpc/auth_unix.c create mode 100644 krb5-1-7/src/lib/rpc/authgss_prot.c create mode 100644 krb5-1-7/src/lib/rpc/authunix_prot.c create mode 100644 krb5-1-7/src/lib/rpc/bindresvport.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_generic.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_perror.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_raw.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_simple.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_tcp.c create mode 100644 krb5-1-7/src/lib/rpc/clnt_udp.c create mode 100644 krb5-1-7/src/lib/rpc/deps create mode 100644 krb5-1-7/src/lib/rpc/dyn.c create mode 100644 krb5-1-7/src/lib/rpc/dyn.h create mode 100644 krb5-1-7/src/lib/rpc/dynP.h create mode 100644 krb5-1-7/src/lib/rpc/dyntest.c create mode 100644 krb5-1-7/src/lib/rpc/get_myaddress.c create mode 100644 krb5-1-7/src/lib/rpc/getrpcent.c create mode 100644 krb5-1-7/src/lib/rpc/getrpcport.c create mode 100644 krb5-1-7/src/lib/rpc/gssrpcint.h create mode 100644 krb5-1-7/src/lib/rpc/libgssrpc.exports create mode 100644 krb5-1-7/src/lib/rpc/pmap_clnt.c create mode 100644 krb5-1-7/src/lib/rpc/pmap_getmaps.c create mode 100644 krb5-1-7/src/lib/rpc/pmap_getport.c create mode 100644 krb5-1-7/src/lib/rpc/pmap_prot.c create mode 100644 krb5-1-7/src/lib/rpc/pmap_prot2.c create mode 100644 krb5-1-7/src/lib/rpc/pmap_rmt.c create mode 100644 krb5-1-7/src/lib/rpc/rpc_callmsg.c create mode 100644 krb5-1-7/src/lib/rpc/rpc_commondata.c create mode 100644 krb5-1-7/src/lib/rpc/rpc_dtablesize.c create mode 100644 krb5-1-7/src/lib/rpc/rpc_prot.c create mode 100644 krb5-1-7/src/lib/rpc/svc.c create mode 100644 krb5-1-7/src/lib/rpc/svc_auth.c create mode 100644 krb5-1-7/src/lib/rpc/svc_auth_gss.c create mode 100644 krb5-1-7/src/lib/rpc/svc_auth_gssapi.c create mode 100644 krb5-1-7/src/lib/rpc/svc_auth_none.c create mode 100644 krb5-1-7/src/lib/rpc/svc_auth_unix.c create mode 100644 krb5-1-7/src/lib/rpc/svc_raw.c create mode 100644 krb5-1-7/src/lib/rpc/svc_run.c create mode 100644 krb5-1-7/src/lib/rpc/svc_simple.c create mode 100644 krb5-1-7/src/lib/rpc/svc_tcp.c create mode 100644 krb5-1-7/src/lib/rpc/svc_udp.c create mode 100644 krb5-1-7/src/lib/rpc/unit-test/Makefile.in create mode 100644 krb5-1-7/src/lib/rpc/unit-test/client.c create mode 100644 krb5-1-7/src/lib/rpc/unit-test/config/unix.exp create mode 100644 krb5-1-7/src/lib/rpc/unit-test/deps create mode 100644 krb5-1-7/src/lib/rpc/unit-test/lib/helpers.exp create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test.0/expire.exp create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test.h create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test.x create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test_clnt.c create mode 100755 krb5-1-7/src/lib/rpc/unit-test/rpc_test_setup.sh create mode 100644 krb5-1-7/src/lib/rpc/unit-test/rpc_test_svc.c create mode 100644 krb5-1-7/src/lib/rpc/unit-test/server.c create mode 100644 krb5-1-7/src/lib/rpc/xdr.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_alloc.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_array.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_float.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_mem.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_rec.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_reference.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_sizeof.c create mode 100644 krb5-1-7/src/lib/rpc/xdr_stdio.c create mode 100644 krb5-1-7/src/lib/win_glue.c create mode 100644 krb5-1-7/src/lib/xpprof32.def create mode 100644 krb5-1-7/src/patchlevel.h create mode 100644 krb5-1-7/src/plugins/authdata/greet/Makefile.in create mode 100644 krb5-1-7/src/plugins/authdata/greet/deps create mode 100644 krb5-1-7/src/plugins/authdata/greet/greet.exports create mode 100644 krb5-1-7/src/plugins/authdata/greet/greet_auth.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/adb_openclose.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/adb_policy.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/db2.exports create mode 100644 krb5-1-7/src/plugins/kdb/db2/db2_exp.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/kdb_db2.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/kdb_db2.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/kdb_xdr.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/kdb_xdr.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/CHANGELOG.db2 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/README create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/README.db2 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_close.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_conv.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_debug.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_delete.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_get.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_open.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_page.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_put.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_search.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_seq.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_split.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/bt_utils.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/btree.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/btree/extern.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/db/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/db/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/db/db.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/db/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/btree.3.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/hash.3.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/docs/recno.3.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/dbm.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/extern.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash.c.patch create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash_debug.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash_func.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash_log2.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hash_page.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/hsearch.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/page.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/page.h.patch create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/hash/search.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/config.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db-config.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db-dbm.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db-int.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db-ndbm.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db-queue.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/include/db.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/libdb.exports create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db.man.ps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_btree.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_hash.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_lock.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_log.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_mpool.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_open.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_recno.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/db_txn.3 create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/man/spell.ok create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/README create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/mpool.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/mpool/mpool.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/Makefile.inc create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/extern.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_close.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_delete.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_get.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_open.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_put.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_search.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_seq.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/rec_utils.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/recno/recno.h create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/README create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/dbtest.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/deps create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/dictionary create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash2.tests/README create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/libdb2/test/run.test create mode 100644 krb5-1-7/src/plugins/kdb/db2/pol_xdr.c create mode 100644 krb5-1-7/src/plugins/kdb/db2/policy_db.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/ldap/deps create mode 100644 krb5-1-7/src/plugins/kdb/ldap/kldap.exports create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_exp.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/deps create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/deps create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c create mode 100644 krb5-1-7/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h create mode 100644 krb5-1-7/src/plugins/locate/python/Makefile.in create mode 100644 krb5-1-7/src/plugins/locate/python/deps create mode 100644 krb5-1-7/src/plugins/locate/python/locate-service.py create mode 100644 krb5-1-7/src/plugins/locate/python/py-locate.c create mode 100644 krb5-1-7/src/plugins/locate/python/python.exports create mode 100644 krb5-1-7/src/plugins/preauth/cksum_body/Makefile.in create mode 100644 krb5-1-7/src/plugins/preauth/cksum_body/cksum_body.exports create mode 100644 krb5-1-7/src/plugins/preauth/cksum_body/cksum_body_main.c create mode 100644 krb5-1-7/src/plugins/preauth/cksum_body/deps create mode 100644 krb5-1-7/src/plugins/preauth/encrypted_challenge/Makefile.in create mode 100644 krb5-1-7/src/plugins/preauth/encrypted_challenge/deps create mode 100644 krb5-1-7/src/plugins/preauth/encrypted_challenge/encrypted_challenge.exports create mode 100644 krb5-1-7/src/plugins/preauth/encrypted_challenge/encrypted_challenge_main.c create mode 100644 krb5-1-7/src/plugins/preauth/fast_factor.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/Makefile.in create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/deps create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkcs11.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit.exports create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_accessor.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_accessor.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_clnt.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_crypto.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_identity.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_lib.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_matching.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_profile.c create mode 100644 krb5-1-7/src/plugins/preauth/pkinit/pkinit_srv.c create mode 100644 krb5-1-7/src/plugins/preauth/wpse/Makefile.in create mode 100644 krb5-1-7/src/plugins/preauth/wpse/deps create mode 100644 krb5-1-7/src/plugins/preauth/wpse/wpse.exports create mode 100644 krb5-1-7/src/plugins/preauth/wpse/wpse_main.c create mode 100644 krb5-1-7/src/prototype/getopt.c create mode 100644 krb5-1-7/src/prototype/prototype.c create mode 100644 krb5-1-7/src/prototype/prototype.h create mode 100644 krb5-1-7/src/slave/Makefile.in create mode 100644 krb5-1-7/src/slave/deps create mode 100644 krb5-1-7/src/slave/kprop.M create mode 100644 krb5-1-7/src/slave/kprop.c create mode 100644 krb5-1-7/src/slave/kprop.h create mode 100644 krb5-1-7/src/slave/kpropd.M create mode 100644 krb5-1-7/src/slave/kpropd.c create mode 100644 krb5-1-7/src/slave/kpropd_rpc.c create mode 100644 krb5-1-7/src/slave/kproplog.M create mode 100644 krb5-1-7/src/slave/kproplog.c create mode 100644 krb5-1-7/src/slave/kslave_update create mode 100644 krb5-1-7/src/t_krbconf create mode 100644 krb5-1-7/src/tests/Makefile.in create mode 100644 krb5-1-7/src/tests/asn.1/Makefile.in create mode 100644 krb5-1-7/src/tests/asn.1/README create mode 100644 krb5-1-7/src/tests/asn.1/debug.h create mode 100644 krb5-1-7/src/tests/asn.1/deps create mode 100644 krb5-1-7/src/tests/asn.1/krb5_decode_test.c create mode 100644 krb5-1-7/src/tests/asn.1/krb5_encode_test.c create mode 100644 krb5-1-7/src/tests/asn.1/ktest.c create mode 100644 krb5-1-7/src/tests/asn.1/ktest.h create mode 100644 krb5-1-7/src/tests/asn.1/ktest_equal.c create mode 100644 krb5-1-7/src/tests/asn.1/ktest_equal.h create mode 100644 krb5-1-7/src/tests/asn.1/ldap_encode.out create mode 100644 krb5-1-7/src/tests/asn.1/ldap_trval.out create mode 100644 krb5-1-7/src/tests/asn.1/reference_encode.out create mode 100644 krb5-1-7/src/tests/asn.1/t_trval.c create mode 100644 krb5-1-7/src/tests/asn.1/trval.c create mode 100644 krb5-1-7/src/tests/asn.1/trval_reference.out create mode 100644 krb5-1-7/src/tests/asn.1/utility.c create mode 100644 krb5-1-7/src/tests/asn.1/utility.h create mode 100644 krb5-1-7/src/tests/create/Makefile.in create mode 100644 krb5-1-7/src/tests/create/deps create mode 100644 krb5-1-7/src/tests/create/kdb5_mkdums.M create mode 100644 krb5-1-7/src/tests/create/kdb5_mkdums.c create mode 100644 krb5-1-7/src/tests/dejagnu/Makefile.in create mode 100644 krb5-1-7/src/tests/dejagnu/config/default.exp create mode 100644 krb5-1-7/src/tests/dejagnu/deps create mode 100644 krb5-1-7/src/tests/dejagnu/krb-root/rlogin.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-root/telnet.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/gssapi.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/gssftp.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/iprop.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/kadmin.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/kprop.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/princexpire.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/pwchange.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/pwhist.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/rcp.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/rsh.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/sample.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/simple.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/standalone.exp create mode 100644 krb5-1-7/src/tests/dejagnu/krb-standalone/tcp.exp create mode 100644 krb5-1-7/src/tests/dejagnu/t_inetd.c create mode 100644 krb5-1-7/src/tests/deps create mode 100644 krb5-1-7/src/tests/dump.c create mode 100644 krb5-1-7/src/tests/gss-threads/Makefile.in create mode 100644 krb5-1-7/src/tests/gss-threads/README create mode 100644 krb5-1-7/src/tests/gss-threads/deps create mode 100644 krb5-1-7/src/tests/gss-threads/gss-client.c create mode 100644 krb5-1-7/src/tests/gss-threads/gss-misc.c create mode 100644 krb5-1-7/src/tests/gss-threads/gss-misc.h create mode 100644 krb5-1-7/src/tests/gss-threads/gss-server.c create mode 100644 krb5-1-7/src/tests/gssapi/Makefile.in create mode 100644 krb5-1-7/src/tests/gssapi/deps create mode 100644 krb5-1-7/src/tests/gssapi/t_imp_name.c create mode 100644 krb5-1-7/src/tests/hammer/Makefile.in create mode 100644 krb5-1-7/src/tests/hammer/deps create mode 100644 krb5-1-7/src/tests/hammer/kdc5_hammer.c create mode 100644 krb5-1-7/src/tests/hammer/pp.c create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/kdc_pri_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/kdc_ref_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priCL_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_1_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_2_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_3_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_4_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_5_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_6_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_7_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_8_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_priKDC_template.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/input_conf/krb5_ref_template.conf create mode 100644 krb5-1-7/src/tests/kdc_realm/input_conf/test_KDCs.conf create mode 100644 krb5-1-7/src/tests/kdc_realm/input_conf/test_KDCs_1.conf create mode 100644 krb5-1-7/src/tests/kdc_realm/input_conf/test_princs.conf create mode 100644 krb5-1-7/src/tests/kdc_realm/input_conf/test_setup.conf create mode 100755 krb5-1-7/src/tests/kdc_realm/kdcref.py create mode 100644 krb5-1-7/src/tests/misc/Makefile.in create mode 100644 krb5-1-7/src/tests/misc/deps create mode 100644 krb5-1-7/src/tests/misc/test_cxx_gss.cpp create mode 100644 krb5-1-7/src/tests/misc/test_cxx_k5int.cpp create mode 100644 krb5-1-7/src/tests/misc/test_cxx_kadm5.cpp create mode 100644 krb5-1-7/src/tests/misc/test_cxx_krb5.cpp create mode 100644 krb5-1-7/src/tests/misc/test_cxx_rpc.cpp create mode 100644 krb5-1-7/src/tests/misc/test_getpw.c create mode 100644 krb5-1-7/src/tests/misc/test_getsockname.c create mode 100644 krb5-1-7/src/tests/misc/test_nfold.c create mode 100644 krb5-1-7/src/tests/mkeystash_compat/Makefile.in create mode 100644 krb5-1-7/src/tests/mkeystash_compat/bigendian.c create mode 100644 krb5-1-7/src/tests/mkeystash_compat/deps create mode 100644 krb5-1-7/src/tests/mkeystash_compat/old_stash_bendian create mode 100644 krb5-1-7/src/tests/mkeystash_compat/old_stash_lendian create mode 100644 krb5-1-7/src/tests/resolve/Makefile.in create mode 100644 krb5-1-7/src/tests/resolve/addrinfo-test.c create mode 100644 krb5-1-7/src/tests/resolve/deps create mode 100644 krb5-1-7/src/tests/resolve/fake-addrinfo-test.c create mode 100644 krb5-1-7/src/tests/resolve/resolve.c create mode 100644 krb5-1-7/src/tests/shlib/Makefile.in create mode 100644 krb5-1-7/src/tests/shlib/deps create mode 100644 krb5-1-7/src/tests/shlib/t_loader.c create mode 100644 krb5-1-7/src/tests/test1.c create mode 100644 krb5-1-7/src/tests/threads/Makefile.in create mode 100644 krb5-1-7/src/tests/threads/deps create mode 100644 krb5-1-7/src/tests/threads/prof1.c create mode 100644 krb5-1-7/src/tests/threads/t_rcache.c create mode 100644 krb5-1-7/src/tests/verify/Makefile.in create mode 100644 krb5-1-7/src/tests/verify/deps create mode 100644 krb5-1-7/src/tests/verify/kdb5_verify.c create mode 100644 krb5-1-7/src/tests/verify/pkey.c create mode 100644 krb5-1-7/src/util/Makefile.in create mode 100644 krb5-1-7/src/util/ac_check_krb5.m4 create mode 100755 krb5-1-7/src/util/check-ac-syms create mode 100644 krb5-1-7/src/util/collected-client-lib/Makefile.in create mode 100644 krb5-1-7/src/util/collected-client-lib/deps create mode 100644 krb5-1-7/src/util/collected-client-lib/libcollected.exports create mode 100644 krb5-1-7/src/util/def-check.pl create mode 100644 krb5-1-7/src/util/depfix.pl create mode 100644 krb5-1-7/src/util/deps create mode 100644 krb5-1-7/src/util/et/ISSUES create mode 100644 krb5-1-7/src/util/et/Makefile.in create mode 100644 krb5-1-7/src/util/et/com_err.3 create mode 100644 krb5-1-7/src/util/et/com_err.c create mode 100644 krb5-1-7/src/util/et/com_err.h create mode 100644 krb5-1-7/src/util/et/com_err.texinfo create mode 100644 krb5-1-7/src/util/et/compile_et.1 create mode 100644 krb5-1-7/src/util/et/compile_et.c create mode 100755 krb5-1-7/src/util/et/compile_et.sh create mode 100644 krb5-1-7/src/util/et/compiler.h create mode 100755 krb5-1-7/src/util/et/config_script create mode 100644 krb5-1-7/src/util/et/deps create mode 100644 krb5-1-7/src/util/et/error_message.c create mode 100644 krb5-1-7/src/util/et/error_table.h create mode 100644 krb5-1-7/src/util/et/error_table.y create mode 100644 krb5-1-7/src/util/et/et.exp create mode 100644 krb5-1-7/src/util/et/et.pbexp create mode 100644 krb5-1-7/src/util/et/et1.et create mode 100644 krb5-1-7/src/util/et/et2.et create mode 100644 krb5-1-7/src/util/et/et_c.awk create mode 100644 krb5-1-7/src/util/et/et_c.pl create mode 100644 krb5-1-7/src/util/et/et_h.awk create mode 100644 krb5-1-7/src/util/et/et_h.pl create mode 100644 krb5-1-7/src/util/et/et_lex.lex.l create mode 100644 krb5-1-7/src/util/et/et_name.c create mode 100644 krb5-1-7/src/util/et/init_et.c create mode 100644 krb5-1-7/src/util/et/internal.h create mode 100644 krb5-1-7/src/util/et/libcom_err.exports create mode 100644 krb5-1-7/src/util/et/mit-sipb-copyright.h create mode 100644 krb5-1-7/src/util/et/t_com_err.c create mode 100644 krb5-1-7/src/util/et/test1.et create mode 100644 krb5-1-7/src/util/et/test2.et create mode 100644 krb5-1-7/src/util/et/test_et.c create mode 100644 krb5-1-7/src/util/et/texinfo.tex create mode 100644 krb5-1-7/src/util/exitsleep.c create mode 100755 krb5-1-7/src/util/export-check.pl create mode 100755 krb5-1-7/src/util/find-missing-eol-prop create mode 100755 krb5-1-7/src/util/fix-eol-prop create mode 100644 krb5-1-7/src/util/gen-map.pl create mode 100644 krb5-1-7/src/util/gen.pl create mode 100755 krb5-1-7/src/util/getsyms create mode 100644 krb5-1-7/src/util/getsyms.sed create mode 100755 krb5-1-7/src/util/kbuild create mode 100644 krb5-1-7/src/util/kfrags/athena.conf create mode 100644 krb5-1-7/src/util/kfrags/base.conf create mode 100644 krb5-1-7/src/util/kfrags/cns.conf create mode 100644 krb5-1-7/src/util/kfrags/gcc.conf create mode 100644 krb5-1-7/src/util/kfrags/ranlib.conf create mode 100644 krb5-1-7/src/util/kfrags/shared.conf create mode 100644 krb5-1-7/src/util/kfrags/sunpro.conf create mode 100644 krb5-1-7/src/util/kfrags/svr4.conf create mode 100644 krb5-1-7/src/util/kfrags/ucb.conf create mode 100644 krb5-1-7/src/util/ktemplate.pm create mode 100755 krb5-1-7/src/util/lndir create mode 100644 krb5-1-7/src/util/mac/k5_mig.defs create mode 100644 krb5-1-7/src/util/mac/k5_mig_client.c create mode 100644 krb5-1-7/src/util/mac/k5_mig_client.h create mode 100644 krb5-1-7/src/util/mac/k5_mig_reply.defs create mode 100644 krb5-1-7/src/util/mac/k5_mig_request.defs create mode 100644 krb5-1-7/src/util/mac/k5_mig_server.c create mode 100644 krb5-1-7/src/util/mac/k5_mig_server.h create mode 100644 krb5-1-7/src/util/mac/k5_mig_types.h create mode 100755 krb5-1-7/src/util/mkrel create mode 100644 krb5-1-7/src/util/profile/Makefile.in create mode 100644 krb5-1-7/src/util/profile/argv_parse.c create mode 100644 krb5-1-7/src/util/profile/argv_parse.h create mode 100644 krb5-1-7/src/util/profile/deps create mode 100644 krb5-1-7/src/util/profile/dosshell.ini create mode 100644 krb5-1-7/src/util/profile/krb5.conf create mode 100644 krb5-1-7/src/util/profile/libprofile.exports create mode 100644 krb5-1-7/src/util/profile/prof_FSp_glue.c create mode 100644 krb5-1-7/src/util/profile/prof_err.et create mode 100644 krb5-1-7/src/util/profile/prof_file.c create mode 100644 krb5-1-7/src/util/profile/prof_get.c create mode 100644 krb5-1-7/src/util/profile/prof_init.c create mode 100644 krb5-1-7/src/util/profile/prof_int.h create mode 100644 krb5-1-7/src/util/profile/prof_parse.c create mode 100644 krb5-1-7/src/util/profile/prof_set.c create mode 100644 krb5-1-7/src/util/profile/prof_test1 create mode 100644 krb5-1-7/src/util/profile/prof_tree.c create mode 100644 krb5-1-7/src/util/profile/profile.5 create mode 100644 krb5-1-7/src/util/profile/profile.exp create mode 100644 krb5-1-7/src/util/profile/profile.hin create mode 100644 krb5-1-7/src/util/profile/profile.pbexp create mode 100644 krb5-1-7/src/util/profile/profile.swg create mode 100644 krb5-1-7/src/util/profile/profile_tcl.c create mode 100644 krb5-1-7/src/util/profile/prtest.in create mode 100644 krb5-1-7/src/util/profile/prtest.script create mode 100644 krb5-1-7/src/util/profile/test.ini create mode 100644 krb5-1-7/src/util/profile/test_parse.c create mode 100644 krb5-1-7/src/util/profile/test_profile.c create mode 100755 krb5-1-7/src/util/reconf create mode 100644 krb5-1-7/src/util/send-pr/COPYING create mode 100644 krb5-1-7/src/util/send-pr/INSTALL create mode 100644 krb5-1-7/src/util/send-pr/MANIFEST create mode 100644 krb5-1-7/src/util/send-pr/Makefile.in create mode 100644 krb5-1-7/src/util/send-pr/README create mode 100644 krb5-1-7/src/util/send-pr/categories create mode 100644 krb5-1-7/src/util/send-pr/deps create mode 100644 krb5-1-7/src/util/send-pr/install-sid.sh create mode 100644 krb5-1-7/src/util/send-pr/send-pr.1 create mode 100644 krb5-1-7/src/util/send-pr/send-pr.sh create mode 100644 krb5-1-7/src/util/ss/Makefile.in create mode 100644 krb5-1-7/src/util/ss/cmd_tbl.lex.l create mode 100755 krb5-1-7/src/util/ss/config_script create mode 100644 krb5-1-7/src/util/ss/copyright.h create mode 100644 krb5-1-7/src/util/ss/ct.y create mode 100644 krb5-1-7/src/util/ss/ct_c_awk.in create mode 100644 krb5-1-7/src/util/ss/ct_c_sed.in create mode 100644 krb5-1-7/src/util/ss/data.c create mode 100644 krb5-1-7/src/util/ss/deps create mode 100644 krb5-1-7/src/util/ss/error.c create mode 100644 krb5-1-7/src/util/ss/execute_cmd.c create mode 100644 krb5-1-7/src/util/ss/help.c create mode 100644 krb5-1-7/src/util/ss/invocation.c create mode 100644 krb5-1-7/src/util/ss/list_rqs.c create mode 100644 krb5-1-7/src/util/ss/listen.c create mode 100644 krb5-1-7/src/util/ss/mit-sipb-copyright.h create mode 100644 krb5-1-7/src/util/ss/mk_cmds.c create mode 100755 krb5-1-7/src/util/ss/mk_cmds.sh create mode 100644 krb5-1-7/src/util/ss/options.c create mode 100644 krb5-1-7/src/util/ss/pager.c create mode 100644 krb5-1-7/src/util/ss/parse.c create mode 100644 krb5-1-7/src/util/ss/prompt.c create mode 100644 krb5-1-7/src/util/ss/request_tbl.c create mode 100644 krb5-1-7/src/util/ss/requests.c create mode 100644 krb5-1-7/src/util/ss/ss.h create mode 100644 krb5-1-7/src/util/ss/ss_err.et create mode 100644 krb5-1-7/src/util/ss/ss_internal.h create mode 100644 krb5-1-7/src/util/ss/std_rqs.ct create mode 100644 krb5-1-7/src/util/ss/test_ss.c create mode 100644 krb5-1-7/src/util/ss/utils.c create mode 100644 krb5-1-7/src/util/support/Makefile.in create mode 100644 krb5-1-7/src/util/support/cache-addrinfo.h create mode 100644 krb5-1-7/src/util/support/deps create mode 100644 krb5-1-7/src/util/support/errors.c create mode 100644 krb5-1-7/src/util/support/fake-addrinfo.c create mode 100644 krb5-1-7/src/util/support/gmt_mktime.c create mode 100644 krb5-1-7/src/util/support/init-addrinfo.c create mode 100644 krb5-1-7/src/util/support/ipc_stream.c create mode 100644 krb5-1-7/src/util/support/k5buf-int.h create mode 100644 krb5-1-7/src/util/support/k5buf.c create mode 100644 krb5-1-7/src/util/support/libkrb5support-fixed.exports create mode 100644 krb5-1-7/src/util/support/mkstemp.c create mode 100644 krb5-1-7/src/util/support/plugins.c create mode 100644 krb5-1-7/src/util/support/printf.c create mode 100644 krb5-1-7/src/util/support/strlcpy.c create mode 100644 krb5-1-7/src/util/support/supp-int.h create mode 100644 krb5-1-7/src/util/support/t_k5buf.c create mode 100644 krb5-1-7/src/util/support/threads.c create mode 100644 krb5-1-7/src/util/support/utf8.c create mode 100644 krb5-1-7/src/util/support/utf8_conv.c create mode 100644 krb5-1-7/src/util/t_array.pm create mode 100644 krb5-1-7/src/util/t_bimap.pm create mode 100644 krb5-1-7/src/util/t_enum.pm create mode 100644 krb5-1-7/src/util/t_template.pm create mode 100644 krb5-1-7/src/util/t_tsenum.pm create mode 100755 krb5-1-7/src/util/trim-valgrind-logs create mode 100644 krb5-1-7/src/util/valgrind-suppressions create mode 100644 krb5-1-7/src/util/windows/Makefile.in create mode 100644 krb5-1-7/src/util/windows/getopt.c create mode 100644 krb5-1-7/src/util/windows/getopt.h create mode 100644 krb5-1-7/src/util/windows/getopt_long.c create mode 100644 krb5-1-7/src/util/windows/libecho.c create mode 100644 krb5-1-7/src/wconfig.c create mode 100644 krb5-1-7/src/windows/Makefile.in create mode 100644 krb5-1-7/src/windows/README create mode 100644 krb5-1-7/src/windows/build/BKWconfig.xml create mode 100644 krb5-1-7/src/windows/build/Logger.pm create mode 100644 krb5-1-7/src/windows/build/bkw-automation.html create mode 100644 krb5-1-7/src/windows/build/bkw.pl create mode 100644 krb5-1-7/src/windows/build/bootstrap.xml create mode 100644 krb5-1-7/src/windows/build/commandandcontrol.pl create mode 100644 krb5-1-7/src/windows/build/copyfiles.pl create mode 100644 krb5-1-7/src/windows/build/copyfiles.xml create mode 100644 krb5-1-7/src/windows/build/corebinaryfiles.xml create mode 100644 krb5-1-7/src/windows/build/css/main-action(1).css create mode 100644 krb5-1-7/src/windows/build/css/main-action.css create mode 100644 krb5-1-7/src/windows/build/makeZip.pl create mode 100644 krb5-1-7/src/windows/build/pruneFiles.pl create mode 100644 krb5-1-7/src/windows/build/repository1.pl create mode 100644 krb5-1-7/src/windows/build/sdkfiles.xml create mode 100644 krb5-1-7/src/windows/build/signFiles.pl create mode 100644 krb5-1-7/src/windows/build/site-local.sed create mode 100644 krb5-1-7/src/windows/build/tee.pl create mode 100644 krb5-1-7/src/windows/build/which.pl create mode 100644 krb5-1-7/src/windows/build/zipXML.pl create mode 100644 krb5-1-7/src/windows/cns/Makefile.in create mode 100644 krb5-1-7/src/windows/cns/clock00.ico create mode 100644 krb5-1-7/src/windows/cns/clock05.ico create mode 100644 krb5-1-7/src/windows/cns/clock10.ico create mode 100644 krb5-1-7/src/windows/cns/clock15.ico create mode 100644 krb5-1-7/src/windows/cns/clock20.ico create mode 100644 krb5-1-7/src/windows/cns/clock25.ico create mode 100644 krb5-1-7/src/windows/cns/clock30.ico create mode 100644 krb5-1-7/src/windows/cns/clock35.ico create mode 100644 krb5-1-7/src/windows/cns/clock40.ico create mode 100644 krb5-1-7/src/windows/cns/clock45.ico create mode 100644 krb5-1-7/src/windows/cns/clock50.ico create mode 100644 krb5-1-7/src/windows/cns/clock55.ico create mode 100644 krb5-1-7/src/windows/cns/clock60.ico create mode 100644 krb5-1-7/src/windows/cns/clockexp.ico create mode 100644 krb5-1-7/src/windows/cns/clocktkt.ico create mode 100644 krb5-1-7/src/windows/cns/cns-help.doc create mode 100644 krb5-1-7/src/windows/cns/cns-help.hlp create mode 100644 krb5-1-7/src/windows/cns/cns-help.hpj create mode 100644 krb5-1-7/src/windows/cns/cns.c create mode 100644 krb5-1-7/src/windows/cns/cns.h create mode 100644 krb5-1-7/src/windows/cns/cns.ico create mode 100644 krb5-1-7/src/windows/cns/cns_reg.c create mode 100644 krb5-1-7/src/windows/cns/cns_reg.h create mode 100644 krb5-1-7/src/windows/cns/cnsres4.rc create mode 100644 krb5-1-7/src/windows/cns/cnsres5.rc create mode 100644 krb5-1-7/src/windows/cns/debug.c create mode 100644 krb5-1-7/src/windows/cns/heap.c create mode 100644 krb5-1-7/src/windows/cns/kerbnet.doc create mode 100644 krb5-1-7/src/windows/cns/kerbnet.hlp create mode 100644 krb5-1-7/src/windows/cns/kerbnet.hpj create mode 100644 krb5-1-7/src/windows/cns/kpasswd.c create mode 100644 krb5-1-7/src/windows/cns/krb5.def create mode 100644 krb5-1-7/src/windows/cns/krbini.h create mode 100644 krb5-1-7/src/windows/cns/options.c create mode 100644 krb5-1-7/src/windows/cns/password.c create mode 100644 krb5-1-7/src/windows/cns/tktlist.c create mode 100644 krb5-1-7/src/windows/cns/tktlist.h create mode 100644 krb5-1-7/src/windows/gina/Makefile.in create mode 100644 krb5-1-7/src/windows/gina/gina.def create mode 100644 krb5-1-7/src/windows/gina/ginastub.c create mode 100644 krb5-1-7/src/windows/gina/ginastub.h create mode 100644 krb5-1-7/src/windows/gss/Makefile.in create mode 100644 krb5-1-7/src/windows/gss/gss-client.c create mode 100644 krb5-1-7/src/windows/gss/gss-misc.c create mode 100644 krb5-1-7/src/windows/gss/gss-misc.h create mode 100644 krb5-1-7/src/windows/gss/gss.c create mode 100644 krb5-1-7/src/windows/gss/gss.def create mode 100644 krb5-1-7/src/windows/gss/gss.h create mode 100644 krb5-1-7/src/windows/gss/gss.ico create mode 100644 krb5-1-7/src/windows/gss/gss.rc create mode 100644 krb5-1-7/src/windows/gss/resource.h create mode 100644 krb5-1-7/src/windows/gss/ver_serv.txt create mode 100644 krb5-1-7/src/windows/identity/Makefile create mode 100644 krb5-1-7/src/windows/identity/apiversion.txt create mode 100644 krb5-1-7/src/windows/identity/config/Makefile create mode 100644 krb5-1-7/src/windows/identity/config/Makefile.w2k create mode 100644 krb5-1-7/src/windows/identity/config/Makefile.w32 create mode 100644 krb5-1-7/src/windows/identity/config/ccsv.pl create mode 100644 krb5-1-7/src/windows/identity/config/csvschema.cfg create mode 100644 krb5-1-7/src/windows/identity/config/netidmgr_intver.h.in create mode 100644 krb5-1-7/src/windows/identity/config/netidmgr_version.h.in create mode 100644 krb5-1-7/src/windows/identity/doc/Makefile create mode 100644 krb5-1-7/src/windows/identity/doc/cred_aquisition.h create mode 100644 krb5-1-7/src/windows/identity/doc/cred_data_types.h create mode 100644 krb5-1-7/src/windows/identity/doc/cred_main.h create mode 100644 krb5-1-7/src/windows/identity/doc/cred_msgs.h create mode 100644 krb5-1-7/src/windows/identity/doc/cred_prop_pages.h create mode 100644 krb5-1-7/src/windows/identity/doc/doxyfile.cfg create mode 100644 krb5-1-7/src/windows/identity/doc/footer.html create mode 100644 krb5-1-7/src/windows/identity/doc/header.html create mode 100644 krb5-1-7/src/windows/identity/doc/images/credview-select-outline.jpg create mode 100644 krb5-1-7/src/windows/identity/doc/images/khimaira_logo.png create mode 100644 krb5-1-7/src/windows/identity/doc/images/khimaira_logo_small.png create mode 100644 krb5-1-7/src/windows/identity/doc/images/modules_plugins_krb5.png create mode 100644 krb5-1-7/src/windows/identity/doc/main_page.h create mode 100755 krb5-1-7/src/windows/identity/doc/netidmgr.doc create mode 100755 krb5-1-7/src/windows/identity/doc/netidmgr.pdf create mode 100644 krb5-1-7/src/windows/identity/doc/plugin_framework.h create mode 100644 krb5-1-7/src/windows/identity/doc/plugin_locale.h create mode 100644 krb5-1-7/src/windows/identity/doc/plugin_main.h create mode 100644 krb5-1-7/src/windows/identity/doc/plugin_structure.h create mode 100644 krb5-1-7/src/windows/identity/doc/stylesheet.css create mode 100644 krb5-1-7/src/windows/identity/doc/ui_actions.h create mode 100644 krb5-1-7/src/windows/identity/doc/ui_context.h create mode 100644 krb5-1-7/src/windows/identity/doc/ui_main.h create mode 100644 krb5-1-7/src/windows/identity/doc/ui_menus.h create mode 100644 krb5-1-7/src/windows/identity/help/Index.hhk create mode 100644 krb5-1-7/src/windows/identity/help/Makefile create mode 100644 krb5-1-7/src/windows/identity/help/html/about_netidmgr.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_chpw.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_destroy_creds.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_import_creds.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_new_creds.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_renew_creds.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/act_set_default.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/bugs.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/cmdline_netidmgr.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/concept_cred_pro.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/concept_credential.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/concept_ident_pro.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/concept_identity.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/concepts.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/copyright.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/howdoi.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/images/appicon_empty.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/appicon_expired.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/appicon_good.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/appicon_warnexp.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/appicon_warning.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/flag-critical.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/flag-warning.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/flag_expired.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/flag_renewable.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/id-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/logo.jpg create mode 100644 krb5-1-7/src/windows/identity/help/html/images/logo_shade.jpg create mode 100644 krb5-1-7/src/windows/identity/help/html/images/notification_icon_menu.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_app_icon.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_chng_pwd.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_appearance.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_cred_provider.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_general.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_global_krb4.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_global_krb5.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_ident.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_ident_krb4.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_ident_krb5.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_ident_provider.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_idents.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_notifications.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_config_plug_ins.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_main_wnd.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_main_wnd_basic.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_bar.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_credential.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_file.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_help.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_options.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_view.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_menu_view_cols.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_new_creds.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_new_creds_err01.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_new_creds_exp.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_tb_standard.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/screen_tray_icon.png create mode 100644 krb5-1-7/src/windows/identity/help/html/images/wdg_collapsed_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/wdg_expanded_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/wdg_stick_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/images/wdg_stuck_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_all.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_credential.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_file.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_help.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_options.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/menu_view.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/nidmgr.css create mode 100644 krb5-1-7/src/windows/identity/help/html/tb_standard.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/template.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/use_config.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/use_icon.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/use_layout.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/use_start.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/using.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/welcome.htm create mode 100644 krb5-1-7/src/windows/identity/help/html/wnd_main.htm create mode 100644 krb5-1-7/src/windows/identity/help/khhelp.h create mode 100644 krb5-1-7/src/windows/identity/help/netidmgr.hhp create mode 100644 krb5-1-7/src/windows/identity/help/popups.txt create mode 100644 krb5-1-7/src/windows/identity/help/popups_newcreds.txt create mode 100644 krb5-1-7/src/windows/identity/help/popups_password.txt create mode 100644 krb5-1-7/src/windows/identity/help/toc.hhc create mode 100644 krb5-1-7/src/windows/identity/include/Makefile create mode 100644 krb5-1-7/src/windows/identity/include/khdefs.h create mode 100644 krb5-1-7/src/windows/identity/include/kherror.h create mode 100644 krb5-1-7/src/windows/identity/include/khlist.h create mode 100644 krb5-1-7/src/windows/identity/include/khmsgtypes.h create mode 100644 krb5-1-7/src/windows/identity/include/netidmgr.h create mode 100644 krb5-1-7/src/windows/identity/kconfig/Makefile create mode 100644 krb5-1-7/src/windows/identity/kconfig/api.c create mode 100644 krb5-1-7/src/windows/identity/kconfig/kconfig.h create mode 100644 krb5-1-7/src/windows/identity/kconfig/kconfiginternal.h create mode 100644 krb5-1-7/src/windows/identity/kconfig/kconfigmain.c create mode 100644 krb5-1-7/src/windows/identity/kconfig/registry.c create mode 100644 krb5-1-7/src/windows/identity/kconfig/test/utiltest.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/Makefile create mode 100644 krb5-1-7/src/windows/identity/kcreddb/attrib.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/attrib.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/buf.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/buf.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credential.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credential.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credset.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credset.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credtype.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/credtype.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/identity.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/identity.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/init.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/kcdbconfig.csv create mode 100644 krb5-1-7/src/windows/identity/kcreddb/kcreddb.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/kcreddbinternal.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/kcreddbmain.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/lang/en_us/kcredres.rc create mode 100644 krb5-1-7/src/windows/identity/kcreddb/langres.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/resource.h create mode 100644 krb5-1-7/src/windows/identity/kcreddb/type.c create mode 100644 krb5-1-7/src/windows/identity/kcreddb/type.h create mode 100644 krb5-1-7/src/windows/identity/kherr/Makefile create mode 100644 krb5-1-7/src/windows/identity/kherr/kherr.c create mode 100644 krb5-1-7/src/windows/identity/kherr/kherr.h create mode 100644 krb5-1-7/src/windows/identity/kherr/kherrinternal.h create mode 100644 krb5-1-7/src/windows/identity/kherr/kherrmain.c create mode 100644 krb5-1-7/src/windows/identity/kmm/Makefile create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm.h create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm_module.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm_plugin.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm_reg.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kmm_registrar.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kmmconfig.csv create mode 100644 krb5-1-7/src/windows/identity/kmm/kmminternal.h create mode 100644 krb5-1-7/src/windows/identity/kmm/kmmmain.c create mode 100644 krb5-1-7/src/windows/identity/kmm/kplugin.h create mode 100644 krb5-1-7/src/windows/identity/kmm/lang/kmm_msgs.mc create mode 100644 krb5-1-7/src/windows/identity/kmq/Makefile create mode 100644 krb5-1-7/src/windows/identity/kmq/consumer.c create mode 100644 krb5-1-7/src/windows/identity/kmq/init.c create mode 100644 krb5-1-7/src/windows/identity/kmq/kmq.h create mode 100644 krb5-1-7/src/windows/identity/kmq/kmqconfig.csv create mode 100644 krb5-1-7/src/windows/identity/kmq/kmqinternal.h create mode 100644 krb5-1-7/src/windows/identity/kmq/kmqmain.c create mode 100644 krb5-1-7/src/windows/identity/kmq/msgtype.c create mode 100644 krb5-1-7/src/windows/identity/kmq/publisher.c create mode 100644 krb5-1-7/src/windows/identity/nidmgrdll/Makefile create mode 100644 krb5-1-7/src/windows/identity/nidmgrdll/Makefile.w2k create mode 100644 krb5-1-7/src/windows/identity/nidmgrdll/dllmain.c create mode 100644 krb5-1-7/src/windows/identity/nidmgrdll/nidmgrdll.rc create mode 100644 krb5-1-7/src/windows/identity/plugins/common/Makefile create mode 100644 krb5-1-7/src/windows/identity/plugins/common/dynimport.c create mode 100644 krb5-1-7/src/windows/identity/plugins/common/dynimport.h create mode 100644 krb5-1-7/src/windows/identity/plugins/common/krb5common.c create mode 100644 krb5-1-7/src/windows/identity/plugins/common/krb5common.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/Makefile create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/errorfuncs.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/errorfuncs.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/images/plugin.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4configdlg.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4funcs.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4funcs.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4main.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4newcreds.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krb4plugin.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krbconfig.csv create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/krbcred.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/lang/en_us/langres.rc create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/langres.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb4/version.rc create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/Makefile create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/datarep.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/datarep.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/errorfuncs.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/errorfuncs.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/images/deleted.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/images/krb5plugin.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/images/modified.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/images/new.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/images/normal.ico create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5configcc.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5configdlg.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5configid.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5configids.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5funcs.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5funcs.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5identpro.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5main.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5newcreds.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5plugin.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krb5props.c create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krbconfig.csv create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/krbcred.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/lang/en_us/langres.rc create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/langres.h create mode 100644 krb5-1-7/src/windows/identity/plugins/krb5/version.rc create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/Makefile create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/README create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/config_id.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/config_ids.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/config_main.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/credacq.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/credprov.h create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/credtype.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/images/plugin.ico create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/lang/en_us/langres.rc create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/langres.h create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/main.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/plugin.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/proppage.c create mode 100644 krb5-1-7/src/windows/identity/sample/templates/credprov/version.rc create mode 100644 krb5-1-7/src/windows/identity/ui/Makefile create mode 100644 krb5-1-7/src/windows/identity/ui/Makefile.w2k create mode 100644 krb5-1-7/src/windows/identity/ui/aboutwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/aboutwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/addrchange.c create mode 100644 krb5-1-7/src/windows/identity/ui/addrchange.h create mode 100644 krb5-1-7/src/windows/identity/ui/appglobal.h create mode 100644 krb5-1-7/src/windows/identity/ui/appver.rc create mode 100644 krb5-1-7/src/windows/identity/ui/cfg_appear_wnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/cfg_general_wnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/cfg_identities_wnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/cfg_notif_wnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/cfg_plugins_wnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/configwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/configwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/credfuncs.c create mode 100644 krb5-1-7/src/windows/identity/ui/credfuncs.h create mode 100644 krb5-1-7/src/windows/identity/ui/credwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/credwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/debugfuncs.c create mode 100644 krb5-1-7/src/windows/identity/ui/debugfuncs.h create mode 100644 krb5-1-7/src/windows/identity/ui/htwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/htwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_notify_error.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_notify_info.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_notify_none.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_notify_warn.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_state_exp.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_state_ok.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/app_state_warn.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_applied.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_default.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_deleted.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_mod.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_plugin.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_plugin_dis.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/cfg_plugin_err.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/chpw-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/chpw-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/chpw-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/chpw.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/disabled.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/enabled.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/flag-critical.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/flag-warning.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/flag_expired.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/flag_renewable.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/help-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/help.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-delete-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-delete-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-delete-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-delete.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-new-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-new-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-new-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-new.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-refresh-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-refresh-sm-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-refresh-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-refresh.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/id.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/ident.png create mode 100644 krb5-1-7/src/windows/identity/ui/images/import-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/import-sm-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/import-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/import.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/khimaira-cfg.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/logo_shade.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/main_app.ico create mode 100644 krb5-1-7/src/windows/identity/ui/images/tb-blank-small.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tb-blank.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tb-space.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-delete-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-delete-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-delete-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-delete.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-new-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-new-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-new-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-new.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-refresh-dis-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-refresh-dis.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-refresh-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-refresh.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/tk.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/vw-refresh-sm.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/vw-refresh.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_collapsed.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_collapsed_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_credtype.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_expanded.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_expanded_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_flag.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_stick.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_stick_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_stuck.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/images/wdg_stuck_hi.bmp create mode 100644 krb5-1-7/src/windows/identity/ui/khmapp.h create mode 100644 krb5-1-7/src/windows/identity/ui/lang/en_us/cmdline.rtf create mode 100644 krb5-1-7/src/windows/identity/ui/lang/en_us/khapp.rc create mode 100644 krb5-1-7/src/windows/identity/ui/main.c create mode 100644 krb5-1-7/src/windows/identity/ui/mainmenu.c create mode 100644 krb5-1-7/src/windows/identity/ui/mainmenu.h create mode 100644 krb5-1-7/src/windows/identity/ui/mainwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/mainwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/makeacceldef.pl create mode 100644 krb5-1-7/src/windows/identity/ui/makeactiondef.pl create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.exe.manifest.i386 create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.i386.vc7 create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.i386.vc7.debug create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.i386.vc8 create mode 100644 krb5-1-7/src/windows/identity/ui/netidmgr.manifest.i386.vc8.debug create mode 100644 krb5-1-7/src/windows/identity/ui/newcredwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/newcredwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/notifier.c create mode 100644 krb5-1-7/src/windows/identity/ui/notifier.h create mode 100644 krb5-1-7/src/windows/identity/ui/passwnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/passwnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/propertywnd.c create mode 100644 krb5-1-7/src/windows/identity/ui/propertywnd.h create mode 100644 krb5-1-7/src/windows/identity/ui/reqdaemon.c create mode 100644 krb5-1-7/src/windows/identity/ui/reqdaemon.h create mode 100644 krb5-1-7/src/windows/identity/ui/resource.h create mode 100644 krb5-1-7/src/windows/identity/ui/statusbar.c create mode 100644 krb5-1-7/src/windows/identity/ui/statusbar.h create mode 100644 krb5-1-7/src/windows/identity/ui/taskbar.c create mode 100644 krb5-1-7/src/windows/identity/ui/taskbar.h create mode 100644 krb5-1-7/src/windows/identity/ui/timer.c create mode 100644 krb5-1-7/src/windows/identity/ui/timer.h create mode 100644 krb5-1-7/src/windows/identity/ui/toolbar.c create mode 100644 krb5-1-7/src/windows/identity/ui/toolbar.h create mode 100644 krb5-1-7/src/windows/identity/ui/uiconfig.csv create mode 100644 krb5-1-7/src/windows/identity/uilib/Makefile create mode 100644 krb5-1-7/src/windows/identity/uilib/accel.csv create mode 100644 krb5-1-7/src/windows/identity/uilib/acceldef.cfg create mode 100644 krb5-1-7/src/windows/identity/uilib/action.c create mode 100644 krb5-1-7/src/windows/identity/uilib/actiondef.cfg create mode 100644 krb5-1-7/src/windows/identity/uilib/actions.csv create mode 100644 krb5-1-7/src/windows/identity/uilib/alert.c create mode 100644 krb5-1-7/src/windows/identity/uilib/configui.c create mode 100644 krb5-1-7/src/windows/identity/uilib/configui.h create mode 100644 krb5-1-7/src/windows/identity/uilib/creddlg.c create mode 100644 krb5-1-7/src/windows/identity/uilib/intaction.h create mode 100644 krb5-1-7/src/windows/identity/uilib/intalert.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khaction.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khactiondef.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khalerts.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khconfigui.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khhtlink.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khnewcred.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khprops.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khremote.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khrescache.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khtracker.h create mode 100644 krb5-1-7/src/windows/identity/uilib/khuidefs.h create mode 100644 krb5-1-7/src/windows/identity/uilib/propsheet.c create mode 100644 krb5-1-7/src/windows/identity/uilib/propwnd.c create mode 100644 krb5-1-7/src/windows/identity/uilib/rescache.c create mode 100644 krb5-1-7/src/windows/identity/uilib/trackerwnd.c create mode 100644 krb5-1-7/src/windows/identity/uilib/uibind.c create mode 100644 krb5-1-7/src/windows/identity/uilib/uilibmain.c create mode 100644 krb5-1-7/src/windows/identity/uilib/version.c create mode 100644 krb5-1-7/src/windows/identity/util/Makefile create mode 100644 krb5-1-7/src/windows/identity/util/hashtable.c create mode 100644 krb5-1-7/src/windows/identity/util/hashtable.h create mode 100644 krb5-1-7/src/windows/identity/util/mstring.c create mode 100644 krb5-1-7/src/windows/identity/util/mstring.h create mode 100644 krb5-1-7/src/windows/identity/util/perfstat.c create mode 100644 krb5-1-7/src/windows/identity/util/perfstat.h create mode 100644 krb5-1-7/src/windows/identity/util/sync.c create mode 100644 krb5-1-7/src/windows/identity/util/sync.h create mode 100644 krb5-1-7/src/windows/identity/util/utils.h create mode 100644 krb5-1-7/src/windows/installer/nsis/KfWConfigPage.ini create mode 100644 krb5-1-7/src/windows/installer/nsis/KfWConfigPage2.ini create mode 100644 krb5-1-7/src/windows/installer/nsis/kfw-fixed.nsi create mode 100644 krb5-1-7/src/windows/installer/nsis/kfw.ico create mode 100644 krb5-1-7/src/windows/installer/nsis/kfw.nsi create mode 100644 krb5-1-7/src/windows/installer/nsis/killer.cpp create mode 100644 krb5-1-7/src/windows/installer/nsis/licenses.rtf create mode 100644 krb5-1-7/src/windows/installer/nsis/nsi-includes-tagged.nsi create mode 100644 krb5-1-7/src/windows/installer/nsis/site-local-tagged.nsi create mode 100644 krb5-1-7/src/windows/installer/nsis/utils.nsi create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/bannrbmp.bmp create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/completi.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/custicon.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/dlgbmp.bmp create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/exclamic.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/info.bmp create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/insticon.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/new.bmp create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/removico.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/repairic.ico create mode 100644 krb5-1-7/src/windows/installer/wix/Binary/up.bmp create mode 100644 krb5-1-7/src/windows/installer/wix/Makefile create mode 100644 krb5-1-7/src/windows/installer/wix/config.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/custom/custom.cpp create mode 100644 krb5-1-7/src/windows/installer/wix/custom/custom.h create mode 100644 krb5-1-7/src/windows/installer/wix/features.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/files.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/kfw.wxs create mode 100644 krb5-1-7/src/windows/installer/wix/lang/config_1033.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/lang/license.rtf create mode 100644 krb5-1-7/src/windows/installer/wix/lang/strings_1033.wxl create mode 100644 krb5-1-7/src/windows/installer/wix/lang/ui_1033.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/msi-deployment-guide.txt create mode 100644 krb5-1-7/src/windows/installer/wix/platform.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/property.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/runtime.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/runtime_debug.wxi create mode 100644 krb5-1-7/src/windows/installer/wix/site-local-tagged.wxi create mode 100644 krb5-1-7/src/windows/kfwlogon/Makefile.in create mode 100644 krb5-1-7/src/windows/kfwlogon/kfwcommon.c create mode 100644 krb5-1-7/src/windows/kfwlogon/kfwcpcc.c create mode 100644 krb5-1-7/src/windows/kfwlogon/kfwlogon.c create mode 100644 krb5-1-7/src/windows/kfwlogon/kfwlogon.def create mode 100644 krb5-1-7/src/windows/kfwlogon/kfwlogon.h create mode 100644 krb5-1-7/src/windows/lib/Makefile.in create mode 100644 krb5-1-7/src/windows/lib/cacheapi.h create mode 100644 krb5-1-7/src/windows/lib/gic.c create mode 100644 krb5-1-7/src/windows/lib/gic.h create mode 100644 krb5-1-7/src/windows/lib/registry.c create mode 100644 krb5-1-7/src/windows/lib/registry.h create mode 100644 krb5-1-7/src/windows/lib/vardlg.c create mode 100644 krb5-1-7/src/windows/lib/vardlg.h create mode 100644 krb5-1-7/src/windows/ms2mit/Makefile.in create mode 100644 krb5-1-7/src/windows/ms2mit/mit2ms.c create mode 100644 krb5-1-7/src/windows/ms2mit/ms2mit.c create mode 100644 krb5-1-7/src/windows/ntsecapitest.c create mode 100644 krb5-1-7/src/windows/ntsecapitest.pl create mode 100644 krb5-1-7/src/windows/version.rc create mode 100644 krb5-1-7/src/windows/winlevel.h create mode 100644 krb5-1-7/src/windows/wintel/Makefile.in create mode 100644 krb5-1-7/src/windows/wintel/auth.c create mode 100644 krb5-1-7/src/windows/wintel/auth.h create mode 100644 krb5-1-7/src/windows/wintel/dialog.h create mode 100644 krb5-1-7/src/windows/wintel/edit.c create mode 100644 krb5-1-7/src/windows/wintel/emul.c create mode 100644 krb5-1-7/src/windows/wintel/enc_des.c create mode 100644 krb5-1-7/src/windows/wintel/enc_des.h create mode 100644 krb5-1-7/src/windows/wintel/encrypt.c create mode 100644 krb5-1-7/src/windows/wintel/encrypt.h create mode 100644 krb5-1-7/src/windows/wintel/font.c create mode 100644 krb5-1-7/src/windows/wintel/genget.c create mode 100644 krb5-1-7/src/windows/wintel/ini.h create mode 100644 krb5-1-7/src/windows/wintel/intern.c create mode 100644 krb5-1-7/src/windows/wintel/k5stream.c create mode 100644 krb5-1-7/src/windows/wintel/k5stream.h create mode 100644 krb5-1-7/src/windows/wintel/ktelnet.doc create mode 100644 krb5-1-7/src/windows/wintel/ktelnet.hlp create mode 100644 krb5-1-7/src/windows/wintel/ktelnet.hpj create mode 100644 krb5-1-7/src/windows/wintel/ncsa.ico create mode 100644 krb5-1-7/src/windows/wintel/negotiat.c create mode 100644 krb5-1-7/src/windows/wintel/resource.h create mode 100644 krb5-1-7/src/windows/wintel/screen.c create mode 100644 krb5-1-7/src/windows/wintel/screen.h create mode 100644 krb5-1-7/src/windows/wintel/struct.h create mode 100644 krb5-1-7/src/windows/wintel/telnet.c create mode 100644 krb5-1-7/src/windows/wintel/telnet.def create mode 100644 krb5-1-7/src/windows/wintel/telnet.h create mode 100644 krb5-1-7/src/windows/wintel/telnet.rc create mode 100644 krb5-1-7/src/windows/wintel/telnet_arpa.h create mode 100644 krb5-1-7/src/windows/wintel/telopts.h create mode 100644 krb5-1-7/src/windows/wintel/terminal.ico create mode 100644 krb5-1-7/src/windows/wintel/wt-proto.h diff --git a/krb5-1-7/README b/krb5-1-7/README new file mode 100644 index 000000000..7e2ededcb --- /dev/null +++ b/krb5-1-7/README @@ -0,0 +1,1210 @@ + Kerberos Version 5, Release 1.7.1 + + Release Notes + The MIT Kerberos Team + +Unpacking the Source Distribution +--------------------------------- + +The source distribution of Kerberos 5 comes in a gzipped tarfile, +krb5-1.7.1.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.7.1.tar.gz + +If you don't have GNU tar, you will need to get the FSF gzip +distribution and use gzcat: + + gzcat krb5-1.7.1.tar.gz | tar xpf - + +Both of these methods will extract the sources into krb5-1.7.1/src and +the documentation into krb5-1.7.1/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. + +Keep in mind that unencrypted e-mail is not secure; if you need to +send sensitive information, such as reporting potential security +vulnerabilities, please PGP-encrypt it to our security contact +address: krbcore-security@mit.edu. + +You may view bug reports by visiting + +http://krbdev.mit.edu/rt/ + +and logging in as "guest" with password "guest". + +DES transition +-------------- + +The Data Encryption Standard (DES) is widely recognized as weak. The +krb5-1.7 release will contain measures to encourage sites to migrate +away from using single-DES cryptosystems. Among these is a +configuration variable that enables "weak" enctypes, but will default +to "false" in the future. Additional migration aids are planned for +future releases. + +Major changes in 1.7.1 +---------------------- + +This is primarily a bugfix release. + +* Fix vulnerabilities: MITKRB5-SA-2009-003 [CVE-2009-3295], + MITKRB5-SA-2009-004 [CVE-2009-4212]. + +* Restore compatibility for talking to older kadminds and kadmin + clients for the "addprinc -randkey" operation. + +* Fix some build problems and memory leaks. + +Changes in 1.7.1 by ticket ID +----------------------------- + +1233 need to disable /dev/random use for testing +5668 DAL changes break --with-kdc-kdb-update build +6428 KDC prefers returning KDC_ERR_KEY_EXP vs. KDC_ERR_NAME_EXP +6505 fix t_prf test code properly +6506 Make results of krb5_db_def_fetch_mkey more predictable +6508 kadm5int_acl_parse_restrictions could ref uninitialized variable +6509 kadmind is parsing acls good deref NULL pointer on error +6511 krb5int_rd_chpw_rep could call krb5_free_error with random value +6512 krb5int_yarrow_final could deref NULL if out of memory +6514 minor memory leak in 'none' replay cache type +6515 reduce some mutex performance problems in profile library +6519 krb5_copy_error_message() calls krb5int_clear_error() incorrectly +6530 check for slogin failure in setup_root_shell +6532 (1.7.x) include win-mac.h in gssftp/ftp/cmds.c for HAVE_STDLIB_H +6533 krb5-1.7 cannot be compiled on Debian stable (5.0.2) +6534 getaddrinfo in src/util/support/fake-addrinfo.c causes leak +6536 C++ compatibility for Windows compilation +6540 memory leak in test code t_authdata +6541 Fix memory leak in k5_pac_verify_server_checksum +6542 Check for null characters in pkinit cert fields +6543 Reply message ordering bug in ftpd +6551 Memory leak in spnego accept_sec_context error path +6552 Document kinit -C and -E options +6553 use perror instead of error in kadm5 test suite +6556 Supply LDAP service principal aliases to non-referrals clients +6557 Supply canonical name if present in LDAP iteration +6558 Fix memory leak in gss_krb5int_copy_ccache +6559 Fix parsing of GSS exported names +6568 Fix addprinc -randkey when policy requires multiple character classes +6571 krb5 1.7 memory leak +6573 Fix preauth looping in krb5_get_init_creds +6579 quoting bug causes solaris pre-10 thread handling bugs +6584 crypto modularity work r22778 broke MD4-DES, MD5-DES cksums +6585 KDC MUST NOT accept ap-request armor in FAST TGS +6587 pkinit-obtained tickets can't make TGS requests +6588 Fix ivec chaining for DES iov encryption +6589 Fix AES IOV decryption of small messages +6594 gss_krb5_copy_ccache() doesn't work with spnego delegation +6608 MITKRB5-SA-2009-003 CVE-2009-3295 KDC null deref in referrals +6633 Use keyed checksum type for DES FAST +6635 Restore interoperability with 1.6 addprinc -randkey +6637 MITKRB5-SA-2009-004 [CVE-2009-4212] integer underflow in AES + and RC4 decryption + +Major changes in 1.7 +-------------------- + +The krb5-1.7 release contains a large number of changes, featuring +improvements in the following broad areas: + +* Compatibility with Microsoft Windows + +* Administrator experience + +* User experience + +* Code quality + +* Protocol evolution + +Compatibility with Microsoft Windows: + +* Follow client principal referrals in the client library when + obtaining initial tickets. + +* KDC can issue realm referrals for service principals based on domain + names. + +* Extensions supporting DCE RPC, including three-leg GSS context setup + and unencapsulated GSS tokens inside SPNEGO. + +* Microsoft GSS_WrapEX, implemented using the gss_iov API, which is + similar to the equivalent SSPI functionality. This is needed to + support some instances of DCE RPC. + +* NTLM recognition support in GSS-API, to facilitate dropping in an + NTLM implementation for improved compatibility with older releases + of Microsoft Windows. + +* KDC support for principal aliases, if the back end supports them. + Currently, only the LDAP back end supports aliases. + +* Support Microsoft set/change password (RFC 3244) protocol in + kadmind. + +* Implement client and KDC support for GSS_C_DELEG_POLICY_FLAG, which + allows a GSS application to request credential delegation only if + permitted by KDC policy. + +Administrator experience: + +* Install header files for the administration API, allowing + third-party software to manipulate the KDC database. + +* Incremental propagation support for the KDC database. + +* Master key rollover support, making it easier to change master key + passwords or encryption types. + +* New libdefaults configuration variable "allow_weak_crypto". NOTE: + Currently defaults to "true", but may default to "false" in a future + release. Setting this variable to "false" will have the effect of + removing weak enctypes (currently defined to be all single-DES + enctypes) from permitted_enctypes, default_tkt_enctypes, and + default_tgs_enctypes. + +User experience: + +* Provide enhanced GSS-API error message including supplementary + details about error conditions. + +* In the replay cache, use a hash over the complete ciphertext to + avoid false-positive replay indications. + +Code quality: + +* Replace many uses of "unsafe" string functions. While most of these + instances were innocuous, they impeded efficient automatic and + manual static code analysis. + +* Fix many instances of resource leaks and similar bugs identified by + static analysis tools. + +* Fix CVE-2009-0844, CVE-2009-0845, CVE-2009-0846, CVE-2009-0847 -- + various vulnerabilities in SPNEGO and ASN.1 code. + +Protocol evolution: + +* Remove support for version 4 of the Kerberos protocol (krb4). + +* Encryption algorithm negotiation (RFC 4537), allowing clients and + application services to negotiate stronger encryption than their KDC + supports. + +* Flexible Authentication Secure Tunneling (FAST), a preauthentiation + framework that can protect the AS exchange from dictionary attacks + on weak user passwords. + +Known bugs by ticket ID +----------------------- + +6481 kdb ldap integration removed rev/recurse kdb5_util dumps +6487 gss_unwrap_iov fails in stream mode +6505 fix t_prf test code properly +6506 Make results of krb5_db_def_fetch_mkey more predictable +6507 kdb5_util update_princ_encryption uses latest mkey instead of + active mkey + +Changes by ticket ID +-------------------- + +194 a stash file is not a keytab +914 keytab add without randomizing key +1165 annoying error message from krb5_mk_priv() +1201 replay cache can produce false positive indications +1624 use more secure checksum types +2836 feature request: compile/link time warnings for deprecated functions +2939 unified CCAPI implementation +3496 krb524d should log success as well as failure +3497 problems with corrupt (truncated) ccaches +3499 race in replay cache file ownership +3737 plugins support requires a Windows equivalent to opendir and friends +3929 support lazy launching of ccapi server +3930 CCAPI server must be able to distinguish context handles from + other server instances +3931 CCAPI context and ccache change times must be stored by the client +3932 CCAPI should use a cc_handle not implemented as a pointer +3933 CCAPI client library reconnection support +3934 Implement CCAPI blocking calls +3935 CCAPI implement locking +3936 krb5_ccache functions should use the ccapi version 3 interface +4241 Command line --version option +5411 MEMORY keytab +5425 nonce needs to be random +5427 buffer overflow in krb5_kt_get_name +5428 MEMORY keytab leaks +5429 MEMORY keytab should use krb5_copy_keyblock +5430 MEMORY keytab's get_entry should set enctypes and kvnos +5431 krb5_kt_get_type should return const char *. +5432 krb5_kt_default_name should take an unsized length +5440 sendto_kdc() not signal safe, doesn't respond well to + staggered TCP responses. +5481 manual test of commit handler +5517 use IP(V6)_PKTINFO in KDC for UDP sockets +5545 uninitialized salt length when reading some keys +5560 threads on Solaris 10 +5561 close-on-exec flags +5565 krb5kdc.M is confused about keytype +5567 don't check for readability resolving SRVTAB: keytab +5568 Move CCAPI sources to krb5 repository +5569 Fixed bugs introduced while moving to krb5 repository +5570 Only use __attribute__ on GNUC compilers +5574 Add advisory locking to CCAPI +5575 don't include time.h in CredentialsCache.h if it's not needed +5578 test commit handler +5580 provide asprintf functionality for internal use +5587 PRF for non-AES enctypes +5589 krb5 trunk no longer builds on Windows - vsnprintf + implementation required +5590 gss krb5 mech enhanced error messages +5593 kadmind crash on Debian AMD64 +5594 Work on compiling CCAPI test suite on Windows +5595 Problems with kpasswd and an IPv6 enviroment +5596 patch for providing a way to set the ok-as-delegate flag +5598 ccs_pipe_t needs copy and release functions +5599 Added new autogenerated file to generate-files-mac target +5600 provide more useful error message when running kpropd on command line +5635 need more dylib_file specs for darwin +5641 kadm5_setkey_principal_3 fix +5642 Remove unused, unlocalizable error strings +5643 Alignment fix +5649 t_ser should no longer use kdb libraries +5654 remap mechanism-specific status codes in mechglue/spnego +5655 authorization-data plugin support in KDC +5657 (Mac-specific) PROG_LIBPATH build fix +5667 listprincs *z is broken +5670 Add documentation for CCAPI +5671 cleanup src/lib/gssapi/krb5/error_map.h on Windows +5672 no unistd.h on Windows +5699 test program build problem +5754 cci_array_move should work when the source and dest positions are equal +5760 stdint.h should only be accessed if HAVE_STDINT_H defined +5771 cc_ccache_set_principal always returns error 227 +5776 profile library memory leaks introduced when malloc returns 0 +5786 Update Release Documentation for KFW 3.2.2 +5804 cc_initalize(ccapi_version_2) should return CC_BAD_API_VERSION + not CC_NOT_SUPP +5805 Add documentation for error codes used for flow control. +5806 Removed NOP line of code from krb5_fcc_next_cred() +5807 can't store delegated krb5 creds when using spnego +5813 cc_ccache_store_credentials should return ccErrBadCredentialsVersion +5814 cci_array_move not returning correct new position +5815 ccs_lock_status_grant_lock granting wrong lock +5822 fixed mispelling in kadmin error message +5828 Include time.h for time() +5835 Kerberos with apple leopard +5863 [no subject] +5864 improve debugging of ticket verification in ksu +5867 krb-priv sequence numbers don't match up in retransmitted requests +5872 Add ccs_pipe_compare +5884 Need CCAPI v2 support for Windows +5885 Remove AppleConnect workaround +5894 krb5int_arcfour_string_to_key does not support utf-8 strings +5899 Compiling krb5-1.6.3 on FreeBSD 7.0-RELEASE +5900 ccs_ccache_reset should check all arguments for NULL +5901 CCAPI v2 support crash when client or server strings are NULL +5902 cci_cred_union_compare_to_credentials_union doesn't work for v5 creds +5903 Fix pointer cast in cc_seq_fetch_NCs_end +5904 cc_set_principal should return error on bad cred version +5905 cc_remove_cred should only remove one cred +5906 Fixed error code remapping +5907 Removed tests for check_cc_context_get_version +5908 Remove C warnings from CCAPI tests +5909 Add CCAPI v2 tests +5911 removed unused header file inclusion CoreFoundation.h +5912 Invalid assignment while trying to set input to NULL +5915 cc_ccache_iterator_release, cc_credentials_iterator_release + leak server memory +5920 CCacheServer should track client iterators +5923 Protect CFBundle calls with mutexes +5925 Windows socket(...) returns SOCKET, not file handle +5926 Added prototype to test function to remove warning. +5943 db creation creates a kadmin/hostname princ but doesn't fix case +5947 krb5_walk_realm_tree broken substring logic +5948 error in filebase+suffix list generation in plugin code +5949 Don't leak memory when multiple arguments are NULL +5954 ksu fails without domain_realm mapping for local host +5960 Move KIM implementation to the krb5 repository +5962 unchecked calls to k5_mutex_lock() interact poorly with finalizers +5963 Profile library should not call rw_access earlier than needed +5964 Re: Fwd: [modauthkerb] [SOLVED] 'Request is a replay' + Basic auth +5966 signed vs unsigned char * warnings in kdb_xdr.c +5967 No prototype when building kdb5_util without krb4 support +5969 Add header for kill() in USE_PASSWORD_SERVER case +5982 cci_credentials_iterator_release using wrong message ID +5989 Add new launchd flags to CCacheServer plist file +5990 kadm5_setkey_principal_3 not copying key_data_ver and key_data_kvno +5993 Masterkey Keytab Stash +5999 fix ktutil listing with timestamp +6000 misc uninitialized-storage accesses +6001 Big endian stash file support +6002 krb5_rc_io_creat should use mkstemp +6005 krb5_get_error_message returns const char * +6009 kdc does not compile with glibc 2.8 +6010 krb5int_gic_opte_copy should copy elements individually +6011 Add EnableTransactions launchd option to CCacheServer +6012 Add EnableTransactions launchd option to KerberosAgent +6013 Stop building Kerberos.app as part of KfM. +6015 gss_export_lucid_sec_context support for SPNEGO +6016 SPNEGO workaround for SAMBA mech OID quirks +6017 KDC virtual address support +6019 Add signal to force KDC to check for changed interfaces +6024 Don't use "ccache" in error string printed to user +6025 Add macro so we don't print deprecated warnings while building KfM +6026 CCacheServer crashes iterating over creds which have been destroyed +6029 kadmind leaks error strings on failures +6031 krb needs better realm lookup logic +6032 test commit handler change +6044 Add Apple Inc. to copyright lists. +6052 Return extended krb5 error strings +6055 KIM API +6066 turn off thread-support debugging code +6070 update DES code copyright notices +6074 Use a valid UTF8 password for randkey password +6075 Open log file for appending only, not also reading +6076 Don't build PKINIT ASN.1 support code if not building PKINIT plugin +6077 krb5_fcc_resolve file locking error on malloc failuer +6080 mac port of kim should not depend on kipc +6081 Conditionalize building of CCAPI ccache type on USE_CCAPI +6083 profile write code should only quote empty strings +6087 Notify clients on ccache deletion +6088 Add support to send CFNotifications on ccache and cache + collection changes +6090 k5_mutex_destroy calls pthread_mutex_destroy with mutex locked +6091 lean client changes +6093 KIM should not provide keytab functions when building lite framework +6094 CCAPI is leaking mach ports +6101 compile-time flag to disable iprop +6103 fix resource leak in USE_PASSWORD_SERVER code +6108 A client can fail to get initial creds if it changes the + password while doing so. +6111 CCAPI should only use one pthread key +6120 increase rpc timeout +6121 dead code in lib/rpc/clnt_udp.c +6131 Removed argument from kipc_client_lookup_server +6133 don't do C99-style mixing declarations with code +6138 Switch KfM back to error tables +6140 CCAPI should use common ipc and stream code +6142 KerberosAgent dialogs jump around the screen +6143 KerberosAgent: Enter Identity text field shouldn't be clear + automatically +6144 KerberosAgent: ignore user interaction while busy +6145 KerberosAgent attach associated dialogs to Select Identity dialog +6146 Client name passed by KIM is incorrect +6147 KerberosAgent Use Defaults button doesn't work +6151 Don't touch keychain if home directory access is disabled +6153 Add KLL error table +6154 Hinge building KLL shim off KIM_TO_KLL_SHIM, not LEAN_CLIENT +6155 KLLastChangedTime should return current time, not 0 +6156 KLL shim layer does not correctly handle options +6157 KIM should remember options and identity if prefs indicate +6158 KerberosAgent should handle multiple clients simultaneously +6159 KerberosAgent should handle zoom button better +6160 KLL should use __attribute ((deprecated)) +6162 kim_options_copy should allow in_options to be KIM_OPTIONS_DEFAULT +6163 Crash in kim_credential_create_from_keytab +6164 KL APIs which take a NULL principal return klParameterErr +6165 kim_options_create sometimes returns KIM_OPTIONS_DEFAULT +6166 preferences should handle KIM_OPTIONS_DEFAULT +6168 prefs should not create empty dictionary for KIM_OPTIONS_DEFAULT +6169 Missing keys in KerberosAgent Info.plist +6170 change password should always reprompt on error +6171 allow kim ui plugins to have any name +6172 kim_ui_plugin_fini sends pointer to context instead of context. +6175 always zero out authentication strings +6176 Test KIM plugin +6179 kim_os_string_create_localized leaks CFStringRef +6181 Free error message returned by krb5_get_error_message +6182 kim test suite reports error messages incorrectly +6183 KerberosAgent enter identity dialog should use default +6184 handle stash file names with missing keytab type spec and colon in path +6185 Merge KerberosIPC into k5_mig support +6186 Move GUI/CLI detection from KerberosIPC into KIM +6187 use KIM_BUILTIN_UI instead of LEAN_CLIENT for builtin UI +6189 remove unused variable in kim_ui_cli_ask_change_password +6190 Use a context to store error table info +6192 Treat unreadable terminal as user cancelled so regression tests work +6193 Remap some of the more confusing krb5 errors +6194 Double free and leak in kim_os_library_get_application_path +6195 Added back KLL test programs +6197 KLCreatePrincipalFromTriplet should work with empty instance +6198 KerberosAgent continues to ignore mouse events after error +6199 don't include "WRFILE:" in call to mktemp +6201 small leak in KDC authdata plugins +6202 kadmind leaks extended error strings +6203 DELEG_POLICY_FLAG for GSS +6210 pa_sam leaks parts of krb5_sam_challenge +6211 pam_sam leaking outer krb5_data created by encode_krb5_sam_response +6214 krb5_change_set_password not freeing chpw_rep contents +6216 Free data in tests so leaks checking is easier +6217 kim_preferences should free old identity before overwriting +6218 kim_ccache_iterator_next leaks principal +6219 kim_os_library_get_caller_name leaks file path +6220 kim_identity_change_password_with_credential leaks krb5_creds +6221 KerberosAgent should clear generic auth prompt +6222 KerberosAgent enter dialog should add entered identities to favorites +6224 KerberosAgent 'no selection' placeholder in ticket options +6225 Remove ipc message sent on cc_context_release +6226 KIM should only display error dialogs if it has displayed UI already +6227 Apple LW_net_trans.patch make KDC rescan network after 30 seconds +6231 Apple split build support +6247 Apple patch: null out pointer in string_to_key after free +6248 Apple patch: destroy Mach ports on unload +6250 Use CFStringGetCStringPtr when possible +6251 Add test for kim_identity_create_from_components +6252 krb5_build_principal_va does not allocate krb5_principal +6254 krb5_build_principal_ext walks off beginning of array +6255 partial rewrite of the ASN.1 encoders +6256 localize format strings, not final error string +6260 KerberosAgent hangs changing pw for passwordless identities +6261 Remove saved password if it fails to get tickets +6262 Only prompt automatically from GUI apps +6264 Avoid duplicate identical dialogs in KIM +6265 KerberosAgent bindings causing crashes +6266 BIND_8_COMPAT no longer needed in Leopard +6267 Add _with_password credential acquisition functions to KIM API +6274 Crypto IOV API per Projects/AEAD encryption API +6282 krb5kdc deref uninit memory on the stack on unknown principal (pk-init) +6285 Provide SPI to switch the mach port lookup for kipc +6286 Allow kerberos configuration files fail with EPERM +6289 replay cache is insecurely handled +6290 KIM: Pushing authentication login window do application +6291 Using referrals fills the the credentials cache more entries + of the same name +6294 lib/gssapi/krb5/init_sec_context.c: don't leak on mutex_lock failure +6295 Memory leak in KIM identity object +6297 "make check" fails due to krb5_cc_new_unique() on 64-bit + Solaris SPARC under Sun Studio +6302 kadmind mem leaks [rdar 6358917] +6303 Remove krb4 support +6308 Alignment problem in resolver test +6309 update ldap plugin Makefile for krb4 removal +6315 move generated dependencies out of Makefile.in +6316 KIM GC problem on 64-bit +6335 test failures in password changing +6336 enctype negotiation - etype list +6337 kadmin should force non-forwardable tickets +6339 Fwd: krb5_sendauth vs NAGLE vs DelayedAck +6342 hash db2 code breaks if st_blksize > 64k +6348 kadmin and ktutil installed in sbin, should be bin +6349 lib/rpc tests should not fail if portmap/rpcbind not running +6351 gss_header|trailerlen should be unsigned int +6352 return correct kvno in TGS case +6354 Master Key Migration Project +6355 use t_inetd with a ready message and avoid waiting a lot in + non-root tests +6356 small storage leak in KDC startup +6357 address lib/kadm5 test suite slowness +6358 speed up kpasswd tests +6360 utf8_conv.c: wrong level of indirection in free() +6361 new multi-masterkey support doesn't work well when system + clock is set back +6362 don't do arithmetic on void pointers +6363 int/ptr bug in gssapi code +6364 declare replacement [v]asprintf functions +6365 include omitted system header string.h +6367 Fix a memory leak in krb5_kt_resolve +6368 chpw.c: missing break in switch statement +6370 Fix assertion in gc_frm_kdc.c +6371 deal with memleaks in migrate mkey project +6372 Fix memory handling bug in mk_req_ext +6373 remove some redundant or useless qualifiers +6374 Do not assume sizeof(bool_t) == sizeof(krb5_boolean) +6375 Fix error handling in krb5_walk_realm_tree +6376 Memory handling fixes in walk_rtree +6377 make krb5_free_* functions ignore NULL +6378 Change contract of krb5int_utf8_normalize and fix memory leaks +6379 Fix possible free of uninitialized value in walk_rtree +6390 --disable-rpath is not working +6392 Fix allocation failure check in walk_rtree +6393 Implement TGS authenticator subkey support +6397 use macros for config parameter strings +6398 remove obsolete GNU.ORG realm info +6400 GSSAPI authdata extraction should merge ticket and + authenticator authdata +6401 send_as_req re-encodes the request +6402 CVE-2009-0845 SPNEGO can dereference a null pointer +6403 kdb5_ldap_util create segfaults when + krb5_dbekd_encrypt_key_data() called +6405 fixing several bugs relating to the migrate mkey project using + a LDAP KDB +6407 Make a working krb5_copy_error_message +6408 Report verbose error messages from KDC +6412 crash using library-allocated storage for header in wrap_iov +6415 Use correct salt for canonicalized principals +6418 Improve LDAP admin documentation +6419 Document alias support in LDAP back end +6420 Add LDAP back end support for canonical name attribute +6421 Implement KRB-FX_CF2 +6422 Implement krb5int_find_authdata +6423 krb5_auth_con_free should support freeing a null auth_context + without segfault. +6424 Call kdb_set_mkey_list from the KDC +6425 Memory leak cleanup in ASN.1 +6427 Fix error handling issue in ASN.1 decoder +6431 Install kadmin and kdb headers +6432 Update kdb5_util man page for mkey migration project +6435 Add PAC and principal parsing test cases +6436 Implement FAST from draft-ietf-krb-wg-preauth-framework +6437 mark export grade RC4 as weak +6438 Handle authdata encrypted in subkey +6439 Implement KDC side of TGS FAST +6442 Null pointer defref in adding info +6443 CVE-2009-0844 SPNEGO can read beyond buffer end +6444 CVE-2009-0847 asn1buf_imbed incorrect length validation +6445 CVE-2009-0846 asn1_decode_generaltime can free uninitialized pointer +6449 Fall through on error return +6450 kdc: handle_referral_params does not return ENOMEM errors +6451 Update defaults in documentation +6452 Document allow_weak_crypto +6456 fix memory management in handle_referral_params +6457 KDC realm referral test +6458 use isflagset correctly in TGS referrals +6459 Update kdb5_util man page with missing purge_mkeys command +6460 Implement kinit option for FAST armor ccache +6461 Require fast_req checksum to be keyed +6462 clean up KDC realm referrals error handling +6463 realm referral test cases forcing KRB5_NT_UNKNOWN +6464 verify return code from krb5_db_set_mkey_list +6465 send_tgs.c static analyzer friendliness +6466 check encode_krb5_ap_req return in send_tgs.c +6467 new copy_data_contents variant that null-terminates +6468 k5_utf8s_to_ucs2s could deref NULL pointer... +6469 fcc_generate_new destroys locked mutex on error +6470 Send explicit salt for SALTTYPE_NORMAL keys +6472 typo in ksu error message +6473 strip ok-as-delegate if not in cross-realm TGT chain +6474 move kadmin, ktutil, k5srvutil man pages to man1 +6475 Adding keys to malformed keytabs can infinitely extend the file +6477 make installed headers C++-safe +6478 Fix handling of RET_SEQUENCE flag in mk_priv/mk_ncred +6479 Add DEBUG_ERROR_LOCATIONS support +6480 Do not return PREAUTH_FAILED on unknown preauth +6482 Allow more than 10 past keys to be stored by a policy +6483 man1 in title header for man1 manpages +6484 work around Heimdal not using subkey in TGS-REP +6485 document ok_as_delegate in admin.texinfo +6486 t_pac fails on SPARC Solaris +6488 NFS fails to work with KRB5 1.7 +6489 UCS2 support doesn't handle upper half of BMP +6490 Windows interop with RC4 TGS-REQ subkeys +6492 Remove spurious assertion in handle_authdata +6493 some fixes for 1.7 +6495 Fix test rules for non-gmake make versions +6496 Fix vector initialization error in KDC preauth code +6497 kinit/fast usage message +6498 spnego_mech.c syntax error under _GSS_STATIC_LINK +6499 use printf format attribute only with gcc +6500 use correct type for krb5_c_prf_length length arg +6501 Temporarily disable FAST PKINIT for 1.7 release +6502 typo in doc/api/krb5.tex +6503 typo in admin.texinfo + +Copyright and Other Legal Notices +--------------------------------- + +Copyright (C) 1985-2009 by the Massachusetts Institute of Technology. + +All rights reserved. + +Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Furthermore if you modify this software 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 + +and the initial implementation of incremental propagation, including +the following new or changed files: + + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + slave/kpropd_rpc.c + slave/kproplog.c + +and marked portions of the following files: + + lib/krb5/os/hst_realm.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. + + -------------------- + +Portions contributed by Apple Inc. are subject to the following license: + +Copyright 2004-2008 Apple Inc. All Rights Reserved. + +Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of Apple Inc. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Apple Inc. 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 implementations of strlcpy and strlcat in +src/util/support/strlcat.c have the following copyright and permission +notice: + +Copyright (c) 1998 Todd C. Miller + +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 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. + + -------------------- + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + +The OpenLDAP Public License + Version 2.8, 17 August 2003 + +Redistribution and use of this software and associated documentation +("Software"), with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions in source form must retain copyright statements + and notices, + +2. Redistributions in binary form must reproduce applicable copyright + statements and notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution, and + +3. Redistributions must contain a verbatim copy of this document. + +The OpenLDAP Foundation may revise this license from time to time. +Each revision is distinguished by a version number. You may use +this Software under terms of this license revision or under the +terms of any subsequent revision of the license. + +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS +CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) +OR OWNER(S) OF THE SOFTWARE 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 names of the authors and copyright holders must not be used in +advertising or otherwise to promote the sale, use or other dealing +in this Software without specific, written prior permission. Title +to copyright in this Software shall at all times remain with copyright +holders. + +OpenLDAP is a registered trademark of the OpenLDAP Foundation. + +Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, +California, USA. All Rights Reserved. Permission to copy and +distribute verbatim copies of this document is granted. + + -------------------- + +Marked test programs in src/lib/krb5/krb have the following copyright: + +Copyright (c) 2006 Kungliga Tekniska Högskolan +(Royal Institute of Technology, Stockholm, Sweden). +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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. + +Acknowledgements +---------------- + +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, and also code implementing the Microsoft protocol +extensions. + +Thanks to Sun Microsystems for donating their implementations of +mechglue, SPNEGO, master key rollover, and incremental propagation. + +Thanks to Dennis Ferguson for donating the DES implementation. + +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, Robert Silk, Brad Thompson, Harry Tsai, Zhanna +Tsitkova, Ted Ts'o, Marshall Vale, Tom Yu. diff --git a/krb5-1-7/doc/Makefile b/krb5-1-7/doc/Makefile new file mode 100644 index 000000000..d9b315e30 --- /dev/null +++ b/krb5-1-7/doc/Makefile @@ -0,0 +1,158 @@ +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) + +.PHONY: all +all:: admin-guide-full install-guide-full user-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: 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-7/doc/admin.texinfo b/krb5-1-7/doc/admin.texinfo new file mode 100644 index 000000000..b34a43bad --- /dev/null +++ b/krb5-1-7/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. +Encryption types marked as ``weak'' are available for compatibility +but not recommended for use. + +@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 allow_weak_crypto +If this is set to 0 (for false), then weak encryption types will be +filtered out of the previous three lists (as noted in @ref{Supported +Encryption Types}). The default value for this tag is true, but that +default may change in the future. + +@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 +kdc_req_checksum_type is only used for DES keys. The ap_req_checksum_type defaults to the preferred checksum for the encryption type being used if unset. If set, then the selected checksum is used regardless of the type of key being used. 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 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. + + +@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 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 (created by @code{kdb5_ldap_util stashsrvpw}) 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 (created by @code{kdb5_ldap_util stashsrvpw}) 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,dc=example,dc=com +[dbmodules] + openldap_ldapconf = @{ + db_library = kldap + ldap_kerberos_container_dn = cn=krbcontainer,dc=example,dc=com + ldap_kdc_dn = "cn=krbadmin,dc=example,dc=com" + # this object needs to have read rights on + # the realm container and principal subtrees + ldap_kadmind_dn = "cn=krbadmin,dc=example,dc=com" + # this object needs to have read and write rights on + # the realm container and principal subtrees + 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. +-@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 @{-|+@}ok_as_delegate +The ``+ok_as_delegate'' option sets a flag in tickets issued for the +service principal. Some client programs may recognize this flag as +indicating that it is okay to delegate credentials to the service. If +ok_as_delegate is set on a cross-realm TGT, it indicates that the +foreign realm's ok_as_delegate flags should be honored by clients in +the local realm. The default is ``-ok_as_delegate''. + +@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},dc=example,dc=com @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=dc=example,dc=com -x linkdn=cn=@value{RANDOMUSER2},dc=example,dc=com @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 @{-|+@}ok_as_delegate +@code{+ok_as_delegate} sets the OK-AS-DELEGATE flag on tickets issued for use +with this principal as the service, which clients may use as a hint that +credentials can and should be delegated when authenticating to the service. +(Sets the @samp{KRB5_KDB_OK_AS_DELEGATE} flag.) @code{-ok_as_delegate} 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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu create -sscope 2 +-subtree ou=users,dc=example,dc=com -r ATHENA.MIT.EDU +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu create -sscope 2 +-subtree ou=users,dc=example,dc=com -kdcdn cn=krbkdc,dc=example,dc=com -admindn cn=krbadmin,dc=example,dc=com -r ATHENA.MIT.EDU +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +modify -r ATHENA.MIT.EDU +requires_preauth +@b{Password for "cn=admin,dc=example,dc=com":} +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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu view -r ATHENA.MIT.EDU +@b{Password for "cn=admin,dc=example,dc=com":} +@b{Realm Name: ATHENA.MIT.EDU} +@b{Subtree: ou=users,dc=example,dc=com} +@b{Subtree: ou=servers,dc=example,dc=com} +@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,dc=example,dc=com -H ldap-server1.mit.edu destroy -r ATHENA.MIT.EDU +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu list +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com +@b{Password for "cn=service-kdc,dc=example,dc=com"}: +@b{Re-enter password for "cn=service-kdc,dc=example,dc=com"}: +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,dc=example,dc=com -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,dc=example,dc=com":} +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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu view_policy +-r ATHENA.MIT.EDU usertktpolicy +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +destroy_policy -r ATHENA.MIT.EDU usertktpolicy +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu list_policy -r ATHENA.MIT.EDU +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +create_service -kdc -randpw -f /home/andrew/service_passwd cn=service-kdc,dc=example,dc=com +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +modify_service -realm ATHENA.MIT.EDU cn=service-kdc,dc=example,dc=com +@b{Password for "cn=admin,dc=example,dc=com":} +@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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +view_service cn=service-kdc,dc=example,dc=com +@b{Password for "cn=admin,dc=example,dc=com":} +@b{Service dn: cn=service-kdc,dc=example,dc=com} +@b{Service type: kdc} +@b{Service host list:} +@b{Realm DN list: cn=ATHENA.MIT.EDU,cn=Kerberos,dc=example,dc=com} +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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +destroy_service cn=service-kdc,dc=example,dc=com +@b{Password for "cn=admin,dc=example,dc=com":} +@b{This will delete the service object 'cn=service-kdc,dc=example,dc=com', are you sure?} +@b{(type 'yes' to confirm)? Yes} +@b{** service object 'cn=service-kdc,dc=example,dc=com' 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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu list_service +@b{Password for "cn=admin,dc=example,dc=com":} +@b{cn=service-kdc,dc=example,dc=com} +@b{cn=service-adm,dc=example,dc=com} +@b{cn=service-pwd,dc=example,dc=com} +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,dc=example,dc=com -H ldaps://ldap-server1.mit.edu +setsrvpw -f /home/andrew/conf_keyfile cn=service-kdc,dc=example,dc=com +@b{Password for "cn=admin,dc=example,dc=com":} +@b{Password for "cn=service-kdc,dc=example,dc=com":} +@b{Re-enter password for "cn=service-kdc,dc=example,dc=com":} +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:} addprinc -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:} addprinc -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 +Choose DNs for the KDC and kadmin servers to bind to the LDAP server, +and create them if necessary. These DNs will be specified with the +@code{ldap_kdc_dn} and @code{ldap_kadmind_dn} directives in krb5.conf; +their passwords can be stashed with @code{kdb5_ldap_util stashsrvpw} +and the resulting file specified with the +@code{ldap_service_password_file} directive. + +@item +Choose a DN for the global Kerberos container entry (but do not create +the entry at this time). This DN will be specified with the +@code{ldap_kerberos_container_dn} directive in krb5.conf. Realm +container entries will be created underneath this DN. Principal +entries may exist either underneath the realm container (the default) +or in separate trees referenced from the realm container. + +@item +Configure the LDAP server ACLs to enable the KDC and kadmin server DNs +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 container +access to @code{dn.subtree}= @i{"cn=EXAMPLE.COM,cn=krbcontainer,dc=example,dc=com"} + by @code{dn.exact}=@i{"cn=kdc-service,dc=example,dc=com"} read + by @code{dn.exact}=@i{"cn=adm-service,dc=example,dc=com"} write + by * none + +# Providing access to principals, if not underneath realm container +access to @code{dn.subtree}= @i{"ou=users,dc=example,dc=com"} + by @code{dn.exact}=@i{"cn=kdc-service,dc=example,dc=com"} read + by @code{dn.exact}=@i{"cn=adm-service,dc=example,dc=com"} write + by * none + +access to * + by * read +@end smallexample + +@noindent +If the locations of the container and principals or the DNs of 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,dc=example,dc=com} create @b{-subtrees} @i{ou=users,dc=example,dc=com} @b{-r} @i{EXAMPLE.COM} @b{-s} +@end smallexample + +@noindent +Use the @code{-subtrees} option if the principals are to exist in a separate subtree from the realm container. Before executing the command, make sure that the subtree mentioned above @samp{(ou=users,dc=example,dc=com)} exists. If the principals will exist underneath the realm container, omit the @code{-subtrees} option and do not worry about creating the principal subtree. + +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,dc=example,dc=com} @i{stashsrvpw} @b{-f} @code{/etc/kerberos/service.keyfile} @i{cn=krbadmin,dc=example,dc=com} +@end smallexample + +@item +Add krb5principalname to the indexes in slapd.conf to speed up the access. +@end enumerate + +With the LDAP back end it is possible to provide aliases for principal +entries. Currently we provide no mechanism provided for creating +aliases, so it must be done by direct manipulation of the LDAP +entries. + +An entry with aliases contains multiple values of the krbPrincipalName +attribute. Since LDAP attribute values are not ordered, it is +necessary to specify which principal name is canonical, by using the +krbCanonicalName attribute. Therefore, to create aliases for an +entry, first set the krbCanonicalName attribute of the entry to the +canonical principal name (which should be identical to the +pre-existing krbPrincipalName value), and then add additional +krbPrincipalName attributes for the aliases. + +Principal aliases are only returned by the KDC when the client +requests canonicalization. Canonicalization is normally requested for +service principals; for client principals, an explicit flag is often +required (e.g. @code{kinit -C}) and canonicalization is only performed +for initial ticket requests. + +@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 +@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-7/doc/api/Makefile b/krb5-1-7/doc/api/Makefile new file mode 100644 index 000000000..2d5d6b784 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/ccache.tex b/krb5-1-7/doc/api/ccache.tex new file mode 100644 index 000000000..d6e24e834 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/errors.tex b/krb5-1-7/doc/api/errors.tex new file mode 100644 index 000000000..ad90cac53 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/fancyheadings.sty b/krb5-1-7/doc/api/fancyheadings.sty new file mode 100644 index 000000000..a71de0fb5 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/fixunder.sty b/krb5-1-7/doc/api/fixunder.sty new file mode 100644 index 000000000..b7ae58dbf --- /dev/null +++ b/krb5-1-7/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-7/doc/api/free.tex b/krb5-1-7/doc/api/free.tex new file mode 100644 index 000000000..02733b702 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/functions.sty b/krb5-1-7/doc/api/functions.sty new file mode 100644 index 000000000..a3165f811 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/intro.tex b/krb5-1-7/doc/api/intro.tex new file mode 100644 index 000000000..370775b02 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/keytab.tex b/krb5-1-7/doc/api/keytab.tex new file mode 100644 index 000000000..63e27e538 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/krb5.ist b/krb5-1-7/doc/api/krb5.ist new file mode 100644 index 000000000..36e9adb2b --- /dev/null +++ b/krb5-1-7/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-7/doc/api/krb5.tex b/krb5-1-7/doc/api/krb5.tex new file mode 100644 index 000000000..3e347a47c --- /dev/null +++ b/krb5-1-7/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_SEQUENCE 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-7/doc/api/krb5idx.sty b/krb5-1-7/doc/api/krb5idx.sty new file mode 100644 index 000000000..729ed9779 --- /dev/null +++ b/krb5-1-7/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-7/doc/api/libdes.tex b/krb5-1-7/doc/api/libdes.tex new file mode 100644 index 000000000..71e75c59b --- /dev/null +++ b/krb5-1-7/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-7/doc/api/libos.tex b/krb5-1-7/doc/api/libos.tex new file mode 100644 index 000000000..447044fec --- /dev/null +++ b/krb5-1-7/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-7/doc/api/library.tex b/krb5-1-7/doc/api/library.tex new file mode 100644 index 000000000..713ce482f --- /dev/null +++ b/krb5-1-7/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-7/doc/api/rcache.tex b/krb5-1-7/doc/api/rcache.tex new file mode 100644 index 000000000..28bad36ab --- /dev/null +++ b/krb5-1-7/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-7/doc/api/tables.tex b/krb5-1-7/doc/api/tables.tex new file mode 100644 index 000000000..b272a07b9 --- /dev/null +++ b/krb5-1-7/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-7/doc/bug-report.texinfo b/krb5-1-7/doc/bug-report.texinfo new file mode 100644 index 000000000..9a1767d56 --- /dev/null +++ b/krb5-1-7/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-7/doc/build.texinfo b/krb5-1-7/doc/build.texinfo new file mode 100644 index 000000000..8bf08157e --- /dev/null +++ b/krb5-1-7/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). + +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-7/doc/ccapi/Doxyfile b/krb5-1-7/doc/ccapi/Doxyfile new file mode 100644 index 000000000..734c29c90 --- /dev/null +++ b/krb5-1-7/doc/ccapi/Doxyfile @@ -0,0 +1,281 @@ +# Doxyfile 1.5.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Credentials Cache API " +PROJECT_NUMBER = +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = YES +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = YES +SHOW_INCLUDE_FILES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text " +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../Sources/include/CredentialsCache.h +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = NO +GENERATE_HTMLHELP = NO +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = letter +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = YES +RTF_OUTPUT = rtf +COMPACT_RTF = YES +RTF_HYPERLINKS = YES +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = NO +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = /Volumes/Ragna-Blade/Developer/Doxygen/Doxygen.app/Contents/Resources/ +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/krb5-1-7/doc/ccapi/ccache-api-v2.html b/krb5-1-7/doc/ccapi/ccache-api-v2.html new file mode 100755 index 000000000..b8d3f06e5 --- /dev/null +++ b/krb5-1-7/doc/ccapi/ccache-api-v2.html @@ -0,0 +1,1217 @@ + + + + Credentials Cache API v2 Specification + + +

Credentials Cache API v2 Specification

+

This version of the API is deprecated.
+Please refer to CCAPI version 3 or later for the current API.

+ + + +

+


+ + +

Abstract

+ +

This is the specification for an API which provides Credentials +Cache services for both +Kerberos V5 and V4. +The idea behind this API is that multiple Kerberos implementations +can share a single Credentials Cache, mediated by this API +specification. On the Microsoft Windows platform this will allow +single-signon, even when more than one Kerberos DLL is in use on a +particular system. Ideally, this problem could be solved by +standardizing the Kerberos V5 API library interface. However, the +Kerberos API is complicated enough that this would be hard to +accomplish. Standardizing the interface for credentials cache access +is much simpler. This API has also been adopted in the MIT Kerberos +for the Macintosh implementation. + +

This specification has been revised to allow storage and +manipulation of both V4 and V5 tickets. A cache contains one or more +"Named Cache"s. It is assumed that V4 and V5 credentials would each +be stored in separate "Named Cache"s and not mixed in a single "Named +Cache". + +

Below, "NC" refers to "Named Cache".
+ + + +

+


+ + +

Revision History/Notes

+ +

Original version (Draft Version 1)

+ +

1/27/96 by +Theodore Ts'o + +

Revision 2 (Draft Version 1)

+ +

970628 by Steve Rothwell +for the V4Cache Team (Paul Hill, Jenny Khuon, Jean Luker, Dave +Detlefs, Allan Bjorklund, & Steve Rothwell) + +

+ +

Revision 3 (Draft Version 1)

+ +

970725 by Steve Rothwell after initial implementation and alpha +release. The term "credentials cache" was previously used to mean +both "the main cache" and individual "named cache"s within the main +cache. I have started using the term "NC" for "named cache" to make +the distinction clearer and to reduce the overloading of the word +"cache". + +

Changes made for revision 3 of this API:
+ +
    +
  • Added cred version type to cc_create() & cc_open() + +
  • New functions + +
      +
    • cc_get_NC_info(), returns NC_info list for all NCs + +
    • cc_free_NC_info(), frees NC_info list + +
    • cc_get_cred_version(), returns version type of NC + +
    • cc_get_name(), returns name of NC + +
    • cc_free_name(), frees name aquired via cc_get_name() + +
    • cc_seq_fetch_NCs(), iterate over all NCs +
    + +
  • New return codes + +
      +
    • CC_BAD_PARM + +
    • CC_ERR_CACHE_ATTACH + +
    • CC_ERR_CACHE_RELEASE + +
    • CC_ERR_CACHE_FULL + +
    • CC_ERR_CRED_VERSION +
    + +
  • Modified functions + +
      +
    • cc_create(), cc_open(), pass version type of NC + +
    • cc_store(), cc_remove(), cc_ +
    + +
  • New & Modified typedefs & data structures + +
      +
    • cc_cred_vers { CC_CRED_VUNKNOWN, CC_CRED_V4, CC_CRED_V5 } + +
    • cred_ptr_union : contains pointer to credentials (either V4 + or V5) + +
    • cred_union : contains version type and cred_ptr_union + +
    • modified V4Cred_type + +
    • enum StringToKey_Type { STK_AFS or STK_DES } + +
    • copies of the maximum V4 string size indicators + KRB_PRINCIPAL_SZ, KRB_SERVICE_SZ, KRB_INSTANCE_SZ, + KRB_REALM_SZ, ADDR_SZ +
    +
+ +

Revision 4 (Draft Version 1)

+ +

970908 by Steve Rothwell to incorporate changes initiated by Ted +Tso. Further changes are expected in the comments for cc_create() and +cc_get_change_time(). + +

Revision 4a (Final Version 1)

+ +

980603 by Scott McGuire to +correct typographical errors, HTML errors, and minor clarifications. +Final API Version 1 spec. + +

Revision 5 (Draft Version 2)

+ +

990201 by Scott McGuire. + +

    +
  • Increased API version number to 2. + +
  • Added enum's defining version numbers. + +
  • Changes to cc_initialize() to specify how to deal with + different API version numbers. + +
  • Added description of cc_int32 and cc_uint32 types. + +
  • Change some cc_int32's to cc_uint32's. + +
  • Changed way cc_create() will behave when called on an existing + cache. + +
  • Replaced cc_seq_fetch_NCs() with cc_seq_fetch_NCs_begin(), + cc_seq_fetch_NCs_next(), and cc_seq_fetch_NCs_end(); + +
  • Replaced cc_seq_fetch_creds() with cc_seq_fetch_creds_begin(), + cc_seq_fetch_creds_next(), and cc_seq_fetch_creds_end(); + +
  • Replaced enum type references in structs and function + paramenters with cc_int32 references; + +
  • Replaced int type references in function parameters with + cc_int32; + +
  • Added return type of cc_int32 to all functions; + +
  • Removed #ifdef from cred_union structure; + +
  • Constant definitions and changes to V4Cred_type structure; + +
  • Removed incorrect const ccache_p * parameters from cc_store() + and cc_remove_cred(); + +
  • Added CC_NOERROR and CC_BAD_PARM as possible return codes from + all functions (except no CC_BAD_PARM from cc_shutdown() ); + +
  • Added CC_ERR_CRED_VERSION as possible return code from + cc_open() and cc_create(); + +
  • Moved infoNC structure definition up to be with rest of + structure definitions; + +
  • Changed "struct _infoNC" to "infoNC" in parameter type + references. + +
  • cc_free_principal() and cc_free_name() now take char ** + instead of char * for final parameter. (This change was made + between rev 4a and rev 5, but I'm re-emphasizing it here.) + +
  • Added Implementation Notes section with requirement that all + functions must be atomic and name requirements for Windows DLL's. + +
  • Renamed "the proposed changes to this API are" section to + "Ideas for Future Versions" -- but removed all items but one + because they'd all been done. + +
  • Removed most of the notes about differences with the Win NT/95 + implementation of the API -- the differences have been reconciled. + +
  • Removed unnecessary and inconsistent italicizing. +
+ +

Revsion 5a (Final Version 2)

+ +

990723 by Scott McGuire. + +

    +
  • cc_create(): Removed text about "expected" form of name. + Removed note about "the alpha version does not do this." + +
  • cc_destroy(): Clarified that you do not need to call + cc_close() on the cache_pointer after calling this function. + +
  • Removed note about Windows cc_get_instance() and + cc_set_instance() functions, they are no longer part of the + Windows code! +
+ +

Ideas for Future Versions

+ +
    +
  • Define Get/Set functions for all components of _cc_creds? + (This will allow future changes to the data structure to be + transparent to the caller. This also makes backward compatibility + much easier to maintain.) +
+ +


+ + +


+ + +

Type definitions

+ +
// enums for API versions used in cc_initialize()
+enum {
+   CC_API_VER_1 = 1,
+   CC_API_VER_2 = 2
+};
+ 
+
+// cc_int32 and cc_uint32 are not exactly defined in this API due
+// to a lack of standard 32-bit integer size between platforms
+// (although there is the C9X standard).
+// However, we will place the following constraints:
+//
+// cc_int32 is a signed integer that is at least 32 bits wide.
+// cc_uint32 is an unsigned integer that is at least 32 bits wide
+ 
+
+typedef cc_int32 cc_time_t;  //see notes below
+
+typedef cc_uint32 cc_nc_flags;
+ 
+ 
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct opaque_ccache_pointer_type* ccache_p;
+typedef struct opaque_credential_iterator_type* ccache_cit;
+ 
+// These really are intended to be opaque. All implementations of the cache API must have
+// them but what they are is implementation specific. In the case of SGR's implementation,
+// the cc_ctx returned available after a call to cc_initialize, is a CCache_ctx class object. The 
+// code that normally calls the cc_initialize function is straight C, which means the calling
+// application doesn't have a chance in hell of manipulating this directly. The API is designed
+// so that it does not have to. It does have to pass the pointer to the class around, one reason 
+// being so that the destructor can eventually be called.
+ 
+ 
+
+typedef struct _cc_data {
+    cc_uint32            type;
+    cc_uint32            length;
+    unsigned char*      data;
+} cc_data;
+ 
+
+typedef struct _cc_creds {
+    char*       client; /* client's principal identifier */
+    char*       server; /* server's principal identifier */
+    cc_data     keyblock;       /* session encryption key info */
+    cc_time_t   authtime;
+    cc_time_t   starttime;
+    cc_time_t   endtime;
+    cc_time_t   renew_till;
+    cc_uint32    is_skey;        /* true if ticket is encrypted in
+                                   another ticket's skey */
+    cc_uint32    ticket_flags;   /* flags in ticket */
+    cc_data**   addresses;      /* addrs in ticket */
+    cc_data     ticket;         /* ticket string itself */
+    cc_data     second_ticket;  /* second ticket, if related to
+                                   ticket (via DUPLICATE-SKEY or
+                                   ENC-TKT-IN-SKEY) */
+    cc_data**   authdata;       /* authorization data */
+} cc_creds;
+ 
+ 
+// use an enumerated type so all callers infer the same meaning
+// these values are what krbv4win uses internally.
+
+enum StringToKey_Type { STK_AFS = 0, STK_DES = 1 };
+ 
+enum { MAX_V4_CRED_LEN = 1250 };
+ 
+ 
+// V4 Credentials
+
+enum {
+  KRB_NAME_SZ = 40,
+  KRB_INSTANCE_SZ = 40,
+  KRB_REALM_SZ = 40
+};
+ 
+typedef struct _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; of type enum StringToKey_Type
+    long                       issue_date;             // k95 called this issue_time
+    cc_int32                   lifetime;               // k95 used LONG expiration_time
+    cc_uint32                  address;                // IP Address of local host as an unsigned 32-bit integer
+    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_vers {  
+    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;  // cc_cred_vers
+    cred_ptr_union cred;
+} cred_union;
+ 
+
+typedef struct _infoNC {
+        char*   name;
+        char*   principal;
+        cc_int32 vers;   // cc_cred_vers
+} infoNC;
+ +

The cc_data structure

+ +

The cc_data structure is used to store the following elements: + +

    +
  • keyblock + +
  • addresses + +
  • ticket (and second_ticket) + +
  • authorization data +
+ +

For cc_creds.ticket and cc_creds.second_ticket, the cc_data.type +field MUST be zero. For the cc_creds.addresses, cc_creds.authdata, +and cc_data.keyblock, the cc_data.type field should be the address +type, authorization data type, and encryption type, as defined by the +Kerberos V5 protocol definition. + +

cc_time_t

+ +

The cc_time_t fields are used to represent time. The time must be +stored as the number of seconds since midnight GMT on January 1, +1970. + +

Principal names

+ +

Principal names are stored as C strings in this API. The C strings +may contain UTF-8 encoded strings for internationalization +purposes.
+ + +


+ + +

Error Codes Definition

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

0  +

+

CC_NOERROR  +

+

"Successful return"  +

+

1  +

+

CC_BADNAME  +

+

"Bad credential cache name format"  +

+

2  +

+

CC_NOTFOUD  +

+

"Matching credential not found"  +

+

3  +

+

CC_END  +

+

"End of credential cache reached"  +

+

4  +

+

CC_IO  +

+

"Credentials cache I/O operation failed"  +

+

5  +

+

CC_WRITE  +

+

"Error writing to credentials cache file"  +

+

6  +

+

CC_NOMEM  +

+

"No memory"  +

+

7  +

+

CC_FORMAT  +

+

"Corrupted credentials cache"  +

+

8  +

+

CC_LOCKED  +

+

"The credentials cache or NC is locked"  +

+

9  +

+

CC_BAD_API_VERSION  +

+

"Unsupported API version"  +

+

10  +

+

CC_NO_EXIST  +

+

"Credentials cache or NC does not exist"  +

+

11  +

+

CC_NOT_SUPP  +

+

"Function not supported"  +

+

12  +

+

CC_BAD_PARM  +

+

"Bad Paramter Passed"  +

+

13  +

+

CC_ERR_CACHE_ATTACH  +

+

"Failed to attach cache"  +

+

14  +

+

CC_ERR_CACHE_RELEASE  +

+

"Failed to release cache"  +

+

15  +

+

CC_ERR_CACHE_FULL  +

+

"Cache FULL"  +

+

16  +

+

CC_ERR_CRED_VERSION  +

+

"Wrong Cred Version"  +

+ +

+


+ + +

Implementation Notes

+ +

All functions are atomic

+ +

All Credentials Cache API functions must be atomic. + +

Windows + +

DLLs should be named KrbCC16.dll and KrbCC32.dll. + +

+


+ + +

Function definitions

+ +

+ +

Main Cache Functions

+ +

+ + +

+ +

cc_initialize

+ +
cc_int32 cc_initialize(apiCB** cc_ctx, cc_int32 api_version, cc_int32* api_supported, char** vendor)
+ +

This function performs any initialization required by the +API. It must be called before any other function in the +API is called. The cc_ctx returned by this function must be +passed to all other API functions as the first argument. + +

The application must pass in the maximum version number of the API +it supports in the api_version parameter. + +

If api_supported non-NULL, then cc_initialize will store +the maximum API version number supported by the library implementing +the API there. + +

If the version requested by api_version is not equal to the +version supported by the library, CC_BAD_API_VERSION will be returned +as the error code (along with the version the library does support in +api_supported) and cc_initialize should not allocate any +memory. + +

If the vendor is non-NULL, then cc_initialize will store a +pointer to a read/only C string which contains a string describing +the vendor which implemented the credentials cache API. + +

Possible error codes: CC_NOERROR, CC_NOMEM, CC_BAD_API_VERSION, +CC_BAD_PARM + +


+ + + +

cc_shutdown

+ +
cc_int32 cc_shutdown(apiCB** cc_ctx)
+ +

This function performs any cleanup required by the API. +cc_ctx will be NULL on return. The application program must call +cc_initialize() again before making any credentials cache API +calls. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_get_change_time

+ +
cc_int32 cc_get_change_time(apiCB* cc_ctx, cc_time_t* time)
+ +

This function returns the time of the most recent change for the +entire cache. There is ONE timestamp maintained for the entire cache. +By maintaining a local copy the caller can deduce whether "something +changed" or not. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_NOMEM, +CC_BAD_PARM + +


+ + + +

cc_get_NC_info

+ +
cc_int32 cc_get_NC_info(apiCB* cc_ctx, infoNC*** ppNCi)
+ +

cc_get_NC_info() is a wrapper for cc_seq_fetch_NCs(), +cc_get_name() cc_get_cred_version(), and cc_get_principal(). It +returns all the information needed to uniquely identify each NC in +the cache (name and cred_version) and the associated principal. +Specifically it returns a null terminated list of pointers to infoNC +structs. Each infoNC struct contain a pointer to the NC's name, a +pointer to the the principal associated with the NC, and the version +number (as an enumerated type) of the credentials stored in this NC. + +

The ppNCi (the entire data structure) aquired by this routine +should be freed with cc_free_NC_info(). + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_NOMEM, +CC_BAD_PARM + +


+ + + +

cc_open

+ +
cc_int32 cc_open(apiCB* cc_ctx, const char* name, cc_int32 cred_vers, cc_uint32 cc_flags,
+                 ccache_p** ccache_pointer)
+ +

Opens an already exising NC identified by both name, and +cred_vers. It fills in the parameter **ccache_pointer with a +pointer to the NC. + +

The list of cache names, principals, and credentials versions may +be retrieved via cc_seq_fetch_NCs(), cc_get_name(), +cc_get_cred_version(), & cc_get_principal() OR via +cc_get_NC_info(). + +

Possible error codes: CC_NOERROR, CC_BADNAME, CC_NO_EXIST, +CC_NOMEM, CC_ERR_CRED_VERSION, CC_BAD_PARM + +


+ + + +

cc_create

+ +
cc_int32 cc_create(apiCB* cc_ctx, const char* name, const char* principal,
+                cc_int32 cred_vers, cc_uint32 cc_flags, ccache_p** ccache_pointer)
+ +

Create a new NC. The NC is uniquely identified by the combination +of it's name and the "cc_creds_vers" (i.e. which credentials version +it holds). The principal given is also associated with the NC. A NULL +name is not allowed (and CC_BADNAME should be returned if one +is passed in). If name is non-null and there is already a NC +named name, all credentials in the cache are removed, and +handle for the existing cache is returned. If there is already a NC +named name, all existing handles for this cache remain valid. The NC +is created with a primary principal specified by principal. + +

(Removed text about the "expected" form of the NC name.) + +

An NC is intended to hold credentials for a single principal in a +single realm, and for a single credentials version (i.e. V4 or V5). +The cache can contain credentials for other credential versions, +other realms, and even other principals, but each in a separate NC. +This rule will allow callers that can only handle a single principal +in a single realm to continue to work by dealing with only one NC. +Callers that can deal with multiple principals, multiple realms, +and/or multiple credentials versions can do so by dealing with +multiple NCs. By doing it this way, the callers that are able to +handle multiple principals, realms, and/or versions can do so without +interfering with "differently abled" code. + +

The list of cache names, principals, & cred_versions may be +retrieved via cc_get_NC_info(). + +

Possible error codes: CC_NOERROR, CC_BADNAME, CC_BAD_PARM, +CC_NO_EXIST, CC_NOMEM, CC_ERR_CRED_VERSION + +


+ + + +

cc_close

+ +
cc_int32 cc_close(apiCB* cc_ctx, ccache_p** ccache_pointer)
+ +

Close the NC. The ccache_pointer related memory is +deallocated, and ccache_pointer is set to NULL before being returned +to caller. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_destroy

+ +
cc_int32 cc_destroy(apiCB* cc_ctx, ccache_p** ccache_pointer)
+ +

Destroy the NC pointed to by ccache_pointer. The +ccache_pointer related memory is deallocated, and +ccache_pointer is set to NULL before being returned to caller. The +caller does not need to call cc_close() on the cache_pointer +afterwards. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

+ +

cc_seq_fetch_NCs_begin

+ +
cc_int32 cc_seq_fetch_NCs_begin(apiCB* cc_ctx, ccache_cit** itNCs)
+ +

Used to allocate memory and initialize the iterator *itNCs. Use +cc_seq_fetch_NCs_end() to deallocate the memory used by *itNCs. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM, +CC_NOMEM + +

+ +

cc_seq_fetch_NCs_next

+ +
cc_int32 cc_seq_fetch_NCs_next(apiCB* cc_ctx, ccache_p** ccache_pointer, ccache_cit* itNCs)
+ +

Used to sequentially open every NC in the cache. + +

Ccache_pointer must be a pointer to a ccache_p*. The +ccache_pointer returned may be used to get information about the NC +by calling cc_get_name(), cc_get_cred_version(), and +cc_get_principal(). Ccache_pointer's returned must be freed via +cc_close() between calls to cc_seq_fetch_NCs_next(). + +

itNCs must be a pointer to a ccache_cit* variable provided by the +calling application and which is used by cc_seq_fetch_NCs_next() to +determine the next NC to return. It must have been initialized by +cc_seq_fetch_NCs_begin(). + +

If changes are made to the credentials cache while it iterator is +being used, it must return at least the intersection, and at most the +union, of the set of NC's that were in the cache when the iteration +began and the set of NC's that are in the cache when it ends. + +

When the last NC in the sequence is returned, the return code from +cc_seq_fetch_NCs_next() will be CC_END. + +

Possible error codes: CC_NOERROR, CC_END, CC_NO_EXIST. +CC_BAD_PARM, CC_NOMEM + +

 

+ +

+ +

cc_seq_fetch_NCs_end

+ +
cc_int32 cc_seq_fetch_NCs_end(apiCB* cc_ctx, ccache_cit** itNCs)
+ +

Deallocates the memory used by *itNCs, and sets *itNCs to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +

  + +

+ +

NC Functions

+ +

+ + +

cc_get_name

+ +
cc_int32 cc_get_name(apiCB* cc_ctx, const ccache_p* ccache_pointer, char** name)
+ +

cc_get_name() returns the name of the NC indicated by +ccache_pointer. The name can be used in cc_open() or cc_create(). The +combination of the name and the credentials version uniqeuly identify +an NC. The returned name should be freed via cc_free_name(). + +

Possible error codes: CC_NOERROR, CC_NOMEM, CC_NO_EXIST, +CC_BAD_PARM + +


+ + + +

cc_get_cred_version

+ +
cc_int32 cc_get_cred_version(apiCB* cc_ctx, const ccache_p* ccache_pointer, cc_int32* cred_vers)
+ +

cc_get_cred_version() returns one of the enumerated type +cc_cred_vers in cred_vers. The expected values are CC_CRED_V4, or +CC_CRED_V5. The combination of the name and the credentials version +uniquely identify an NC. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_set_principal

+ +
cc_int32 cc_set_principal(apiCB* cc_ctx, const ccache_p* ccache_pointer, const cc_int32 cred_vers,
+                          const char* principal)
+ +

Set the primary principal for the NC indicated by ccache_pointer. +This is the complement to cc_get_principal(). + +

cred_vers is used as a double check. + +

principal points to a null terminated string that will be copied +into the NC. This new principal will be returned if you call +cc_get_principal() for this NC. + +

Possible error codes: CC_NOERROR, CC_NOMEM, CC_NO_EXIST, +CC_ERR_CRED_VERSION, CC_BAD_PARM
+ +  + +


+ + + +

cc_get_principal

+ +
cc_int32 cc_get_principal(apiCB* cc_ctx, const ccache_p* ccache_pointer, char** principal)
+ +

Return the primary principal for the NC that was set via +cc_create() or cc_set_principal(). The returned principal should be +freed via cc_free_principal() . + +

Possible error codes: CC_NOERROR, CC_NOMEM, CC_NO_EXIST, +CC_BAD_PARM
+ + + +


+ + + +

cc_store

+ +
cc_int32 cc_store(apiCB* cc_ctx, ccache_p* ccache_pointer, const cred_union cred)
+ +

Store (make a copy of) cred in the NC indicated by +ccache_pointer. + +

A cred_union contains a cred_type indicator and a cred_ptr_union. +A cred_ptr_union can contain either a V4Cred_type pointer or a +cc_creds (V5 creds) pointer. Cred_type indicates which type of +pointer is in the cred_ptr_union. This also allows the API to +enforce the credentials version declared in cc_create() or cc_open(). + + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_ERR_CACHE_FULL, +CC_ERR_CRED_VERSION, CC_BAD_PARM + +


+ + + +

cc_remove_cred

+ +
cc_int32 cc_remove_cred(apiCB* cc_ctx, ccache_p* ccache_pointer, const cred_union cred)
+ +

Removes the credential cred from ccache_pointer. The +credentials in the NC indicated by ccache_pointer are searched to +find a matching credential. If found, that credential is removed from +the NC. The cred parameter is not modified and should be freed via +cc_free_creds(). It is legitimate to call this function during a +sequential fetch, and the deletion of a credential already returned +by cc_seq_fetch_creds() should not disturb sequence of credentials +returned by cc_seq_fetch_creds(). + +

Use of cred_union is the same as is explained in cc_store(). + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_NOTFOUND, +CC_ERR_CRED_VERSION, CC_BAD_PARM + +


+ + + +

cc_seq_fetch_creds_begin

+ +
cc_int32 cc_seq_fetch_creds_begin(apiCB* cc_ctx, const ccache_p* ccache_pointer, ccache_cit** itCreds)
+ +

Allocates memory for and initializes *itCreds. This memory must be +deallocated using cc_seq_fetch_creds_end(). + +

Ccache_pointer must be a valid pointer to the NC containing the +creds to be returned by the iterator. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM, +CC_NOMEM + +

  + +

+ +

cc_seq_fetch_creds_next

+ +
cc_int32 cc_seq_fetch_creds_next(apiCB* cc_ctx, cred_union** cred, ccache_cit* itCreds)
+ +

cc_seq_fetch_creds_next() is used to sequentially read every set +of credentials in an NC. The NC has been indicated in the call to +cc_seq_fetch_creds_begin(). + +

itCreds must be a pointer to a ccache_cit* variable provided by +the calling application and which is used by +cc_seq_fetch_creds_next() to determine the next cached credential to +return. The ccache_cit* variable must be initialized by calling +cc_seq_fetch_creds_begin(). + +

The credentials are filled into the cred_union pointed to by +creds. Note that the cred_union contains elements which are +dynamically allocated, so must be freed using cc_free_creds() between +calls to cc_seq_fetch_creds_next(). + +

If changes are made to the NC while it iterator is being used, it +must return at least the intersection, and at most the union, of the +set of credentials that were in the NC when the iteration began and +the set of credentials that are in the NC when it ends. + +

When the last credential in the sequence is returned, the return +code from cc_seq_fetch_creds_next() will be CC_END. + +

Possible error codes: CC_NOERROR, CC_END, CC_NO_EXIST, +CC_BAD_PARM, CC_NOMEM + +

  + +

+ +

cc_seq_fetch_creds_end

+ +
cc_int32 cc_seq_fetch_creds_end(apiCB* cc_ctx, ccache_cit** itCreds)
+ +

Deallocates memory used by *itCreds and sets *itCreds to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_lock_request

+ +
cc_int32 cc_lock_request(apiCB* cc_ctx, const ccache_p* ccache_pointer, cc_int32 lock_type)
+ +
+
99/02/11 - smcguire + +
As of this date there is no locking in the Win NT/95 + or Machintosh implementations. The description below may not be + completely accurate as to how this function should be + implemented. +
+ +

This function is currently NOT IMPLEMENTED. All functions attach +to the cache, take action, and detach from the cache before returning +to the caller. + +

This function will lock or unlock the NC based on the argument +value of lock_type: + +

        CC_LOCK_UNLOCK  1       Unlock the NC
+        CC_LOCK_READER  2       Lock the NC for reading
+        CC_LOCK_WRITER  3       Lock the NC for writing
+ 
+        CC_LOCK_NOBLOCK 16      Don't block, but return an error code if
+                                the request cannot be satisfied.
+ 
+ +

Locking is done on a per-thread basis. At most one thread may have +the credentials locked for writing; if so, there must not be any +threads that have the credentials locked for reading. + +

Multiple threads may have the cache locked for reading, as long as +there is not a writer lock asserted on the cache. + +

If a thread has a cache locked for reading, that lock may be +upgraded to a writer lock by calling cc_lock_request() with a +lock_type of CC_LOCK_WRITER. If a thread has the cache locked for +reading or writing, a request to cc_lock_request() for a reader or +writer lock, respectively, is a no-op. If a thread does not have the +cache locked, and calls cc_lock_request() with a lock_type of +CC_LOCK_UNLOCK, this is also a no-op. + +

A request for CC_LOCK_READER and CC_LOCK_WRITER may be made +non-blocking by logical or'ing the value CC_LOCK_NOBLOCK. In that +case, if it is not possible to satisfy the lock request, the error +CC_LOCKED will be returned. + +

  + +

+ +

Liberation Functions

+ +

+ + +

cc_free_principal

+ +
cc_int32 cc_free_principal(apiCB* cc_ctx, char** principal)
+ +

This function frees the principal returned by +cc_get_principal() and sets *principal to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_free_name

+ +
cc_int32 cc_free_name(apiCB* cc_ctx, char** name)
+ +

This function frees the name returned by cc_get_name() and +sets *name to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_free_creds

+ +
cc_int32 cc_free_creds(apiCB* cc_ctx, cred_union** creds)
+ +

This function frees all storage associated with creds returned by +cc_seq_fetch_creds() and sets the creds pointer to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + +


+ + + +

cc_free_NC_info

+ +
cc_int32 cc_free_NC_info(apiCB* cc_ctx, infoNC*** ppNCi)
+ +

This routine frees all storage aquired by cc_get_NC_info() and +sets ppNCi to NULL. + +

Possible error codes: CC_NOERROR, CC_NO_EXIST, CC_BAD_PARM + + + + + diff --git a/krb5-1-7/doc/ccapi/html/doxygen.css b/krb5-1-7/doc/ccapi/html/doxygen.css new file mode 100644 index 000000000..05615b2e6 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/doxygen.css @@ -0,0 +1,310 @@ +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%; +} +H2 { + font-size: 120%; +} +H3 { + 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: Fixed, monospace; + 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 } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +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 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.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; +} + diff --git a/krb5-1-7/doc/ccapi/html/doxygen.png b/krb5-1-7/doc/ccapi/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/krb5-1-7/doc/ccapi/html/group__cc__ccache__iterator__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__ccache__iterator__reference.html new file mode 100644 index 000000000..2c8bfe27b --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__ccache__iterator__reference.html @@ -0,0 +1,96 @@ + + +Credentials Cache API : cc_ccache_iterator_t Overview + + + + +

cc_ccache_iterator_t Overview


Detailed Description

+The cc_ccache_iterator_t type represents an iterator that iterates over a set of ccaches and returns them in all in some order. A new instance of this type can be obtained by calling cc_context_new_ccache_iterator().

+For API function documentation see cc_ccache_iterator_f. +

+

Data Structures

+ +

Typedefs

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_ccache_iterator_f cc_ccache_iterator_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_ccache_iterator_d cc_ccache_iterator_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_ccache_iterator_d* cc_ccache_iterator_t
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__cc__ccache__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__ccache__reference.html new file mode 100644 index 000000000..ce47b73c6 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__ccache__reference.html @@ -0,0 +1,96 @@ + + +Credentials Cache API : cc_ccache_t Overview + + + + +

cc_ccache_t Overview


Detailed Description

+The cc_ccache_t type represents a reference to a ccache. Callers can access a ccache and the credentials stored in it via a cc_ccache_t. A cc_ccache_t can be acquired via cc_context_open_ccache(), cc_context_open_default_ccache(), or cc_ccache_iterator_next().

+For API function documentation see cc_ccache_f. +

+

Data Structures

+ +

Typedefs

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_ccache_f cc_ccache_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_ccache_d cc_ccache_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_ccache_d* cc_ccache_t
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__cc__context__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__context__reference.html new file mode 100644 index 000000000..cd7e6be3d --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__context__reference.html @@ -0,0 +1,161 @@ + + +Credentials Cache API : cc_context_t Overview + + + + +

cc_context_t Overview


Detailed Description

+The cc_context_t type gives the caller access to a ccache collection. Before being able to call any functions in the CCache API, the caller needs to acquire an instance of cc_context_t by calling cc_initialize().

+For API function documentation see cc_context_f. +

+

Data Structures

+ +

Typedefs

+ +

Functions

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_context_f cc_context_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_context_d cc_context_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_context_d* cc_context_t
+
+ + + + + +
+   + + +

+

+


Function Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CCACHE_API cc_int32 cc_initialize cc_context_t out_context,
cc_int32  in_version,
cc_int32 out_supported_version,
char const **  out_vendor
+
+ + + + + +
+   + + +

+Initialize a new cc_context. +

+

Parameters:
+ + + + + +
out_context on exit, a new context object. Must be free with cc_context_release().
in_version the requested API version. This should be the maximum version the application supports.
out_supported_version if non-NULL, on exit contains the maximum API version supported by the implementation.
out_vendor if non-NULL, on exit contains a pointer to a read-only C string which contains a string describing the vendor which implemented the credentials cache API.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure. May return CCAPI v2 error CC_BAD_API_VERSION if ccapi_version_2 is passed in.
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__cc__credentials__iterator__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__credentials__iterator__reference.html new file mode 100644 index 000000000..41ba42f86 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__credentials__iterator__reference.html @@ -0,0 +1,133 @@ + + +Credentials Cache API : cc_credentials_iterator_t + + + + +

cc_credentials_iterator_t


Detailed Description

+The cc_credentials_iterator_t type represents an iterator that iterates over a set of credentials. A new instance of this type can be obtained by calling cc_ccache_new_credentials_iterator().

+For API function documentation see cc_credentials_iterator_f. +

+

Data Structures

+ +

Typedefs

+ +

Variables

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_credentials_iterator_f cc_credentials_iterator_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_credentials_iterator_d cc_credentials_iterator_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_credentials_iterator_d* cc_credentials_iterator_t
+
+ + + + + +
+   + + +

+

+


Variable Documentation

+

+ + + + +
+ + + + +
cc_int32(* clone)(cc_credentials_iterator_t in_credentials_iterator, cc_credentials_iterator_t *out_credentials_iterator) [inherited]
+
+ + + + + +
+   + + +

+cc_credentials_iterator_clone(): Make a copy of a credentials iterator. +

+

Parameters:
+ + + +
in_credentials_iterator a credentials iterator object.
out_credentials_iterator on exit, a copy of in_credentials_iterator.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__cc__credentials__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__credentials__reference.html new file mode 100644 index 000000000..d083e6c07 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__credentials__reference.html @@ -0,0 +1,197 @@ + + +Credentials Cache API : cc_credentials_t Overview + + + + +

cc_credentials_t Overview


Detailed Description

+The cc_credentials_t type is used to store a single set of credentials for either Kerberos v4 or Kerberos v5. In addition to its only function, release(), it contains a pointer to a cc_credentials_union structure. A cc_credentials_union structure contains an integer of the enumerator type cc_credentials_version, which is either cc_credentials_v4 or cc_credentials_v5, and a pointer union, which contains either a cc_credentials_v4_t pointer or a cc_credentials_v5_t pointer, depending on the value in version.

+Variables of the type cc_credentials_t are allocated by the CCAPI implementation, and should be released with their release() function. API functions which receive credentials structures from the caller always accept cc_credentials_union, which is allocated by the caller, and accordingly disposed by the caller.

+For API functions see cc_credentials_f. +

+

Data Structures

+ +

Typedefs

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_credentials_v4_t cc_credentials_v4_t
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_data cc_data
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_credentials_v5_t cc_credentials_v5_t
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_credentials_union cc_credentials_union
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_credentials_f cc_credentials_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_credentials_d cc_credentials_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_credentials_d* cc_credentials_t
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__cc__string__reference.html b/krb5-1-7/doc/ccapi/html/group__cc__string__reference.html new file mode 100644 index 000000000..9ce3b7195 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__cc__string__reference.html @@ -0,0 +1,96 @@ + + +Credentials Cache API : cc_string_t Overview + + + + +

cc_string_t Overview


Detailed Description

+The cc_string_t represents a C string returned by the API. It has a pointer to the string data and a release() function. This type is used for both principal names and ccache names returned by the API. Principal names may contain UTF-8 encoded strings for internationalization purposes.

+For API function documentation see cc_string_f. +

+

Data Structures

+ +

Typedefs

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef struct cc_string_f cc_string_f
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef struct cc_string_d cc_string_d
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
typedef cc_string_d* cc_string_t
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__ccapi__constants__reference.html b/krb5-1-7/doc/ccapi/html/group__ccapi__constants__reference.html new file mode 100644 index 000000000..87ec30b83 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__ccapi__constants__reference.html @@ -0,0 +1,407 @@ + + +Credentials Cache API : Constants + + + + +

Constants

+

+

Enumerations

+ +

Enumeration Type Documentation

+

+ + + + +
+ + + + +
anonymous enum
+
+ + + + + +
+   + + +

+API version numbers

+These constants are passed into cc_initialize() to indicate the version of the API the caller wants to use.

+CCAPI v1 and v2 are deprecated and should not be used.

Enumerator:
+ + + + + + + + +
ccapi_version_2  +
ccapi_version_3  +
ccapi_version_4  +
ccapi_version_5  +
ccapi_version_6  +
ccapi_version_7  +
ccapi_version_max  +
+
+
+

+ + + + +
+ + + + +
anonymous enum
+
+ + + + + +
+   + + +

+Error codes

Enumerator:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ccNoError  +Success.
ccIteratorEnd  +Iterator is done iterating.
ccErrBadParam  +Bad parameter (NULL or invalid pointer where valid pointer expected).
ccErrNoMem  +Not enough memory to complete the operation.
ccErrInvalidContext  +Context is invalid (e.g., it was released).
ccErrInvalidCCache  +CCache is invalid (e.g., it was released or destroyed).
ccErrInvalidString  +String is invalid (e.g., it was released).
ccErrInvalidCredentials  +Credentials are invalid (e.g., they were released), or they have a bad version.
ccErrInvalidCCacheIterator  +CCache iterator is invalid (e.g., it was released).
ccErrInvalidCredentialsIterator  +Credentials iterator is invalid (e.g., it was released).
ccErrInvalidLock  +Lock is invalid (e.g., it was released).
ccErrBadName  +Bad credential cache name format.
ccErrBadCredentialsVersion  +Credentials version is invalid.
ccErrBadAPIVersion  +Unsupported API version.
ccErrContextLocked  +Context is already locked.
ccErrContextUnlocked  +Context is not locked by the caller.
ccErrCCacheLocked  +CCache is already locked.
ccErrCCacheUnlocked  +CCache is not locked by the caller.
ccErrBadLockType  +Bad lock type.
ccErrNeverDefault  +CCache was never default.
ccErrCredentialsNotFound  +Matching credentials not found in the ccache.
ccErrCCacheNotFound  +Matching ccache not found in the collection.
ccErrContextNotFound  +Matching cache collection not found.
ccErrServerUnavailable  +CCacheServer is unavailable.
ccErrServerInsecure  +CCacheServer has detected that it is running as the wrong user.
ccErrServerCantBecomeUID  +CCacheServer failed to start running as the user.
ccErrTimeOffsetNotSet  +KDC time offset not set for this ccache.
ccErrBadInternalMessage  +The client and CCacheServer can't communicate (e.g., a version mismatch).
ccErrNotImplemented  +API function not supported by this implementation.
ccErrClientNotFound  +CCacheServer has no record of the caller's process (e.g., the server crashed).
+
+
+

+ + + + +
+ + + + +
enum cc_credential_versions
+
+ + + + + +
+   + + +

+Credentials versions

+These constants are used in several places in the API to discern between Kerberos v4 and Kerberos v5. Not all values are valid inputs and outputs for all functions; function specifications below detail the allowed values.

+Kerberos version constants will always be a bit-field, and can be tested as such; for example the following test will tell you if a ccacheVersion includes v5 credentials:

+if ((ccacheVersion & cc_credentials_v5) != 0)

Enumerator:
+ + + + +
cc_credentials_v4  +
cc_credentials_v5  +
cc_credentials_v4_v5  +
+
+
+

+ + + + +
+ + + + +
enum cc_lock_types
+
+ + + + + +
+   + + +

+Lock types

+These constants are used in the locking functions to describe the type of lock requested. Note that all CCAPI locks are advisory so only callers using the lock calls will be blocked by each other. This is because locking functions were introduced after the CCAPI came into common use and we did not want to break existing callers.

Enumerator:
+ + + + + +
cc_lock_read  +
cc_lock_write  +
cc_lock_upgrade  +
cc_lock_downgrade  +
+
+
+

+ + + + +
+ + + + +
enum cc_lock_modes
+
+ + + + + +
+   + + +

+Locking Modes

+These constants are used in the advisory locking functions to describe whether or not the lock function should block waiting for a lock or return an error immediately. For example, attempting to acquire a lock with a non-blocking call will result in an error if the lock cannot be acquired; otherwise, the call will block until the lock can be acquired.

Enumerator:
+ + + +
cc_lock_noblock  +
cc_lock_block  +
+
+
+

+ + + + +
+ + + + +
anonymous enum
+
+ + + + + +
+   + + +

+Sizes of fields in cc_credentials_v4_t.

Enumerator:
+ + + + + + +
cc_v4_name_size  +
cc_v4_instance_size  +
cc_v4_realm_size  +
cc_v4_ticket_size  +
cc_v4_key_size  +
+
+
+

+ + + + +
+ + + + +
enum cc_string_to_key_type
+
+ + + + + +
+   + + +

+String to key type (Kerberos v4 only)

Enumerator:
+ + + + + + +
cc_v4_stk_afs  +
cc_v4_stk_des  +
cc_v4_stk_columbia_special  +
cc_v4_stk_krb5  +
cc_v4_stk_unknown  +
+
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__ccapi__types__reference.html b/krb5-1-7/doc/ccapi/html/group__ccapi__types__reference.html new file mode 100644 index 000000000..9c646b8d9 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__ccapi__types__reference.html @@ -0,0 +1,138 @@ + + +Credentials Cache API : Basic Types + + + + +

Basic Types

+

+

Typedefs

+ +

Typedef Documentation

+

+ + + + +
+ + + + +
typedef uint32_t cc_uint32
+
+ + + + + +
+   + + +

+Unsigned 32-bit integer type

+

+ + + + +
+ + + + +
typedef int32_t cc_int32
+
+ + + + + +
+   + + +

+Signed 32-bit integer type

+

+ + + + +
+ + + + +
typedef int64_t cc_int64
+
+ + + + + +
+   + + +

+Unsigned 64-bit integer type

+

+ + + + +
+ + + + +
typedef uint64_t cc_uint64
+
+ + + + + +
+   + + +

+Signed 64-bit integer type

+

+ + + + +
+ + + + +
typedef cc_uint32 cc_time_t
+
+ + + + + +
+   + + +

+The cc_time_t type is used to represent a time in seconds. The time must be stored as the number of seconds since midnight GMT on January 1, 1970.

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/group__helper__macros.html b/krb5-1-7/doc/ccapi/html/group__helper__macros.html new file mode 100644 index 000000000..cf1c681dc --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/group__helper__macros.html @@ -0,0 +1,1377 @@ + + +Credentials Cache API : CCAPI Function Helper Macros + + + + +

CCAPI Function Helper Macros

+

+

Defines

+ +

Define Documentation

+

+ + + + +
+ + + + + + + + + +
#define cc_context_release context   )    ((context) -> functions -> release (context))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f release()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_context_get_change_time context,
change_time   )    ((context) -> functions -> get_change_time (context, change_time))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f get_change_time()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_context_get_default_ccache_name context,
name   )    ((context) -> functions -> get_default_ccache_name (context, name))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f get_default_ccache_name()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_context_open_ccache context,
name,
ccache   )    ((context) -> functions -> open_ccache (context, name, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f open_ccache()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_context_open_default_ccache context,
ccache   )    ((context) -> functions -> open_default_ccache (context, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f open_default_ccache()

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + +
#define cc_context_create_ccache context,
name,
version,
principal,
ccache   )    ((context) -> functions -> create_ccache (context, name, version, principal, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f create_ccache()

+

+ + + + +
+ + + + + + + + + + + + + + + + + + +
#define cc_context_create_default_ccache context,
version,
principal,
ccache   )    ((context) -> functions -> create_default_ccache (context, version, principal, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f create_default_ccache()

+

+ + + + +
+ + + + + + + + + + + + + + + + + + +
#define cc_context_create_new_ccache context,
version,
principal,
ccache   )    ((context) -> functions -> create_new_ccache (context, version, principal, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f create_new_ccache()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_context_new_ccache_iterator context,
iterator   )    ((context) -> functions -> new_ccache_iterator (context, iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f new_ccache_iterator()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_context_lock context,
type,
block   )    ((context) -> functions -> lock (context, type, block))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f lock()

+

+ + + + +
+ + + + + + + + + +
#define cc_context_unlock context   )    ((context) -> functions -> unlock (context))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f unlock()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_context_compare context,
compare_to,
equal   )    ((context) -> functions -> compare (context, compare_to, equal))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f compare()

+

+ + + + +
+ + + + + + + + + +
#define cc_context_wait_for_change context   )    ((context) -> functions -> wait_for_change (context))
+
+ + + + + +
+   + + +

+Helper macro for cc_context_f wait_for_change()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_release ccache   )    ((ccache) -> functions -> release (ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f release()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_destroy ccache   )    ((ccache) -> functions -> destroy (ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f destroy()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_set_default ccache   )    ((ccache) -> functions -> set_default (ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f set_default()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_get_credentials_version ccache,
version   )    ((ccache) -> functions -> get_credentials_version (ccache, version))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_credentials_version()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_get_name ccache,
name   )    ((ccache) -> functions -> get_name (ccache, name))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_name()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_get_principal ccache,
version,
principal   )    ((ccache) -> functions -> get_principal (ccache, version, principal))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_principal()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_set_principal ccache,
version,
principal   )    ((ccache) -> functions -> set_principal (ccache, version, principal))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f set_principal()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_store_credentials ccache,
credentials   )    ((ccache) -> functions -> store_credentials (ccache, credentials))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f store_credentials()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_remove_credentials ccache,
credentials   )    ((ccache) -> functions -> remove_credentials (ccache, credentials))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f remove_credentials()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_new_credentials_iterator ccache,
iterator   )    ((ccache) -> functions -> new_credentials_iterator (ccache, iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f new_credentials_iterator()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_lock ccache,
type,
block   )    ((ccache) -> functions -> lock (ccache, type, block))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f lock()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_unlock ccache   )    ((ccache) -> functions -> unlock (ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f unlock()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_get_last_default_time ccache,
last_default_time   )    ((ccache) -> functions -> get_last_default_time (ccache, last_default_time))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_last_default_time()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_get_change_time ccache,
change_time   )    ((ccache) -> functions -> get_change_time (ccache, change_time))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_change_time()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_move source,
destination   )    ((source) -> functions -> move (source, destination))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f move()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_compare ccache,
compare_to,
equal   )    ((ccache) -> functions -> compare (ccache, compare_to, equal))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f compare()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_get_kdc_time_offset ccache,
version,
time_offset   )    ((ccache) -> functions -> get_kdc_time_offset (ccache, version, time_offset))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f get_kdc_time_offset()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_ccache_set_kdc_time_offset ccache,
version,
time_offset   )    ((ccache) -> functions -> set_kdc_time_offset (ccache, version, time_offset))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f set_kdc_time_offset()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_clear_kdc_time_offset ccache,
version   )    ((ccache) -> functions -> clear_kdc_time_offset (ccache, version))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f clear_kdc_time_offset()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_wait_for_change ccache   )    ((ccache) -> functions -> wait_for_change (ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_f wait_for_change()

+

+ + + + +
+ + + + + + + + + +
#define cc_string_release string   )    ((string) -> functions -> release (string))
+
+ + + + + +
+   + + +

+Helper macro for cc_string_f release()

+

+ + + + +
+ + + + + + + + + +
#define cc_credentials_release credentials   )    ((credentials) -> functions -> release (credentials))
+
+ + + + + +
+   + + +

+Helper macro for cc_credentials_f release()

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define cc_credentials_compare credentials,
compare_to,
equal   )    ((credentials) -> functions -> compare (credentials, compare_to, equal))
+
+ + + + + +
+   + + +

+Helper macro for cc_credentials_f compare()

+

+ + + + +
+ + + + + + + + + +
#define cc_ccache_iterator_release iterator   )    ((iterator) -> functions -> release (iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_iterator_f release()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_iterator_next iterator,
ccache   )    ((iterator) -> functions -> next (iterator, ccache))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_iterator_f next()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_ccache_iterator_clone iterator,
new_iterator   )    ((iterator) -> functions -> clone (iterator, new_iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_ccache_iterator_f clone()

+

+ + + + +
+ + + + + + + + + +
#define cc_credentials_iterator_release iterator   )    ((iterator) -> functions -> release (iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_credentials_iterator_f release()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_credentials_iterator_next iterator,
credentials   )    ((iterator) -> functions -> next (iterator, credentials))
+
+ + + + + +
+   + + +

+Helper macro for cc_credentials_iterator_f next()

+

+ + + + +
+ + + + + + + + + + + + +
#define cc_credentials_iterator_clone iterator,
new_iterator   )    ((iterator) -> functions -> clone (iterator, new_iterator))
+
+ + + + + +
+   + + +

+Helper macro for cc_credentials_iterator_f clone()

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/index.html b/krb5-1-7/doc/ccapi/html/index.html new file mode 100644 index 000000000..bf920052f --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/index.html @@ -0,0 +1,85 @@ + + +Credentials Cache API : Credentials Cache API (CCAPI) Documentation + + + + +

Credentials Cache API (CCAPI) Documentation

+

+

+Table of Contents

+ + + + + + + + +

+Introduction

+This is the specification for an API which provides Credentials Cache services for both Kerberos v5 and v4. The idea behind this API is that multiple Kerberos implementations can share a single collection of credentials caches, mediated by this API specification. On the Mac OS and Microsoft Windows platforms this will allow single-login, even when more than one Kerberos shared library is in use on a particular system.

+Abstractly, a credentials cache collection contains one or more credentials caches, or ccaches. A ccache is uniquely identified by its name, which is a string internal to the API and not intended to be presented to users. The user presentable identifier of a ccache is its principal.

+Unlike the previous versions of the API, version 3 of the API stores both Kerberos v4 and v5 credentials in the same ccache.

+At any given time, one ccache is the "default" ccache. The exact meaning of a default ccache is OS-specific; refer to implementation requirements for details.

+Error Handling

+All functions of the API return some of the error constants listed FIXME; the exact list of error constants returned by any API function is provided in the function descriptions below.

+When returning an error constant other than ccNoError or ccIteratorEnd, API functions never modify any of the values passed in by reference.

+Synchronization and Atomicity

+Every function in the API is atomic. In order to make a series of calls atomic, callers should lock the ccache or cache collection they are working with to advise other callers not to modify that container. Note that advisory locks are per container so even if you have a read lock on the cache collection other callers can obtain write locks on ccaches in that cache collection.

+Note that iterators do not iterate over ccaches and credentials atomically because locking ccaches and the cache collection over every iteration would degrade performance considerably under high load. However, iterators do guarantee a consistent view of items they are iterating over. Iterators will never return duplicate entries or skip entries when items are removed or added to the container they are iterating over.

+An application can always lock a ccache or the cache collection to guarantee that other callers participating in the advisory locking system do not modify the ccache or cache collection.

+Implementations should not use copy-on-write techniques to implement locks because those techniques imply that same parts of the ccache collection remain visible to some callers even though they are not present in the collection, which is a potential security risk. For example, a copy-on-write technique might make a copy of the entire collection when a read lock is acquired, so as to allow the owner of the lock to access the collection in an apparently unmodified state, while also allowing others to make modifications to the collection. However, this would also enable the owner of the lock to indefinitely (until the expiration time) use credentials that have actually been deleted from the collection.

+Object Memory Management

+The lifetime of an object returned by the API is until release() is called for it. Releasing one object has no effect on existence of any other object. For example, a ccache obtained within a context continue to exist when the context is released.

+Every object returned by the API (cc_context_t, cc_ccache_t, cc_ccache_iterator_t, cc_credentials_t, cc_credentials_iterator_t, cc_string_t) is owned by the caller of the API, and it is the responsibility of the caller to call release() for every object to prevent memory leaks.

+Opaque Types

+All of the opaque high-level types in CCache API are implemented as structures of function pointers and private data. To perform some operation on a type, the caller of the API has to first obtain an instance of that type, and then call the appropriate function pointer from that instance. For example, to call get_change_time() on a cc_context_t, one would call cc_initialize() which creates a new cc_context_t and then call its get_change_time(), like this:

+

 cc_context_t context;
+ cc_int32 err = cc_initialize (&context, ccapi_version_3, nil, nil);
+ if (err == ccNoError)
+ time = context->functions->get_change_time (context)
+

+All API functions also have convenience preprocessor macros, which make the API seem completely function-based. For example, cc_context_get_change_time (context, time) is equivalent to context->functions->get_change_time (context, time). The convenience macros follow the following naming convention:

+The API function some_function()

 cc_type_t an_object;
+ result = an_object->functions->some_function (opaque_pointer, args)
+

+has an equivalent convenience macro of the form cc_type_some_function():

 cc_type_t an_object;
+ result = cc_type_some_function (an_object, args)
+

+The specifications below include the names for both the functions and the convenience macros, in that order. For clarity, it is recommended that clients using the API use the convenience macros, but that is merely a stylistic choice.

+Implementing the API in this manner allows us to extend and change the interface in the future, while preserving compatibility with older clients.

+For example, consider the case when the signature or the semantics of a cc_ccache_t function is changed. The API version number is incremented. The library implementation contains both a function with the old signature and semantics and a function with the new signature and semantics. When a context is created, the API version number used in that context is stored in the context, and therefore it can be used whenever a ccache is created in that context. When a ccache is created in a context with the old API version number, the function pointer structure for the ccache is filled with pointers to functions implementing the old semantics; when a ccache is created in a context with the new API version number, the function pointer structure for the ccache is filled with poitners to functions implementing the new semantics.

+Similarly, if a function is added to the API, the version number in the context can be used to decide whether to include the implementation of the new function in the appropriate function pointer structure or not.


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__ccache__d.html b/krb5-1-7/doc/ccapi/html/structcc__ccache__d.html new file mode 100644 index 000000000..c19aa2b59 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__ccache__d.html @@ -0,0 +1,43 @@ + + +Credentials Cache API : cc_ccache_d Struct Reference + + + + +

cc_ccache_d Struct Reference
+ +[cc_ccache_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const cc_ccache_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__ccache__f.html b/krb5-1-7/doc/ccapi/html/structcc__ccache__f.html new file mode 100644 index 000000000..ddab94ff9 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__ccache__f.html @@ -0,0 +1,722 @@ + + +Credentials Cache API : cc_ccache_f Struct Reference + + + + +

cc_ccache_f Struct Reference


Detailed Description

+Function pointer table for cc_ccache_t. For more information see cc_ccache_t Overview. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_ccache_t io_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_release(): Release memory associated with a cc_ccache_t object. +

+

Parameters:
+ + +
io_ccache the ccache object to release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
Note:
Does not modify the ccache. If you wish to remove the ccache see cc_ccache_destroy().
+
+

+ + + + +
+ + + + +
cc_int32(* destroy)(cc_ccache_t io_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_destroy(): Destroy a ccache. +

+

Parameters:
+ + +
io_ccache the ccache object to destroy and release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Destroy the ccache referred to by io_ccache and releases memory associated with the io_ccache object. After this call io_ccache becomes invalid. If io_ccache was the default ccache, the next ccache in the cache collection (if any) becomes the new default.
+

+ + + + +
+ + + + +
cc_int32(* set_default)(cc_ccache_t io_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_set_default(): Make a ccache the default ccache. +

+

Parameters:
+ + +
io_ccache a ccache object to make the new default ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* get_credentials_version)(cc_ccache_t in_ccache, cc_uint32 *out_credentials_version)
+
+ + + + + +
+   + + +

+cc_ccache_get_credentials_version(): Get the credentials version of a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_credentials_version on exit, the credentials version of in_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+cc_ccache_get_credentials_version() returns one value of the enumerated type cc_credentials_vers. The possible return values are cc_credentials_v4 (if ccache's v4 principal has been set), cc_credentials_v5 (if ccache's v5 principal has been set), or cc_credentials_v4_v5 (if both ccache's v4 and v5 principals have been set). A ccache's principal is set with one of cc_context_create_ccache(), cc_context_create_new_ccache(), cc_context_create_default_ccache(), or cc_ccache_set_principal().
+

+ + + + +
+ + + + +
cc_int32(* get_name)(cc_ccache_t in_ccache, cc_string_t *out_name)
+
+ + + + + +
+   + + +

+cc_ccache_get_name(): Get the name of a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_name on exit, a cc_string_t representing the name of in_ccache. out_name must be released with cc_string_release().
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* get_principal)(cc_ccache_t in_ccache, cc_uint32 in_credentials_version, cc_string_t *out_principal)
+
+ + + + + +
+   + + +

+cc_ccache_get_principal(): Get the principal of a ccache. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_credentials_version the credentials version to get the principal for.
out_principal on exit, a cc_string_t representing the principal of in_ccache. out_principal must be released with cc_string_release().
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Return the principal for the ccache that was set via cc_context_create_ccache(), cc_context_create_default_ccache(), cc_context_create_new_ccache(), or cc_ccache_set_principal(). Principals for v4 and v5 are separate, but should be kept synchronized for each ccache; they can be retrieved by passing cc_credentials_v4 or cc_credentials_v5 in cred_vers. Passing cc_credentials_v4_v5 will result in the error ccErrBadCredentialsVersion.
+

+ + + + +
+ + + + +
cc_int32(* set_principal)(cc_ccache_t io_ccache, cc_uint32 in_credentials_version, const char *in_principal)
+
+ + + + + +
+   + + +

+cc_ccache_set_principal(): Set the principal of a ccache. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_credentials_version the credentials version to set the principal for.
in_principal a C string representing the new principal of in_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Set the a principal for ccache. The v4 and v5 principals can be set independently, but they should always be kept equal, up to differences in string representation between v4 and v5. Passing cc_credentials_v4_v5 in cred_vers will result in the error ccErrBadCredentialsVersion.
+

+ + + + +
+ + + + +
cc_int32(* store_credentials)(cc_ccache_t io_ccache, const cc_credentials_union *in_credentials_union)
+
+ + + + + +
+   + + +

+cc_ccache_store_credentials(): Store credentials in a ccache. +

+

Parameters:
+ + + +
io_ccache a ccache object.
in_credentials_union the credentials to store in io_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Store a copy of credentials in the ccache.

+See the description of the credentials types for the meaning of cc_credentials_union fields.

+Before credentials of a specific credential type can be stored in a ccache, the corresponding principal version has to be set. For example, before you can store Kerberos v4 credentials in a ccache, the Kerberos v4 principal has to be set either by cc_context_create_ccache(), cc_context_create_default_ccache(), cc_context_create_new_ccache(), or cc_ccache_set_principal(); likewise for Kerberos v5. Otherwise, ccErrBadCredentialsVersion is returned.

+

+ + + + +
+ + + + +
cc_int32(* remove_credentials)(cc_ccache_t io_ccache, cc_credentials_t in_credentials)
+
+ + + + + +
+   + + +

+cc_ccache_remove_credentials(): Remove credentials from a ccache. +

+

Parameters:
+ + + +
io_ccache a ccache object.
in_credentials the credentials to remove from io_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Removes credentials from a ccache. Note that credentials must be previously acquired from the CCache API; only exactly matching credentials will be removed. (This places the burden of determining exactly which credentials to remove on the caller, but ensures there is no ambigity about which credentials will be removed.) cc_credentials_t objects can be obtained by iterating over the ccache's credentials with cc_ccache_new_credentials_iterator().

+If found, the credentials are removed from the ccache. The credentials parameter is not modified and should be freed by the caller. It is legitimate to call this function while an iterator is traversing the ccache, and the deletion of a credential already returned by cc_credentials_iterator_next() will not disturb sequence of credentials returned by cc_credentials_iterator_next().

+

+ + + + +
+ + + + +
cc_int32(* new_credentials_iterator)(cc_ccache_t in_ccache, cc_credentials_iterator_t *out_credentials_iterator)
+
+ + + + + +
+   + + +

+cc_ccache_new_credentials_iterator(): Iterate over credentials in a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_credentials_iterator a credentials iterator for io_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Allocates memory for iterator and initializes it. Successive calls to cc_credentials_iterator_next() will return credentials from the ccache.

+If changes are made to the ccache while an iterator is being used on it, the iterator must return at least the intersection, and at most the union, of the set of credentials that were in the ccache when the iteration began and the set of credentials that are in the ccache when it ends.

+

+ + + + +
+ + + + +
cc_int32(* move)(cc_ccache_t io_source_ccache, cc_ccache_t io_destination_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_move(): Move the contents of one ccache into another, destroying the source. +

+

Parameters:
+ + + +
io_source_ccache a ccache object to move.
io_destination_ccache a ccache object replace with the contents of io_source_ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+cc_ccache_move() atomically copies the credentials, credential versions and principals from one ccache to another. On successful completion io_source_ccache will be released and the ccache it points to will be destroyed. Any credentials previously in io_destination_ccache will be replaced with credentials from io_source_ccache. The only part of io_destination_ccache which remains constant is the name. Any other callers referring to io_destination_ccache will suddenly see new data in it.

+Typically cc_ccache_move() is used when the caller wishes to safely overwrite the contents of a ccache with new data which requires several steps to generate. cc_ccache_move() allows the caller to create a temporary ccache (which can be destroyed if any intermediate step fails) and the atomically copy the temporary cache into the destination.

+

+ + + + +
+ + + + +
cc_int32(* lock)(cc_ccache_t io_ccache, cc_uint32 in_lock_type, cc_uint32 in_block)
+
+ + + + + +
+   + + +

+cc_ccache_lock(): Lock a ccache. +

+

Parameters:
+ + + + +
io_ccache the ccache object for the ccache you wish to lock.
in_lock_type the type of lock to obtain.
in_block whether or not the function should block if the lock cannot be obtained immediately.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Attempts to acquire an advisory lock for a ccache. Allowed values for lock_type are:

+

    +
  • cc_lock_read: a read lock.
  • +
  • cc_lock_write: a write lock
  • +
  • cc_lock_upgrade: upgrade an already-obtained read lock to a write lock
  • +
  • cc_lock_downgrade: downgrade an already-obtained write lock to a read lock
  • +
+If block is cc_lock_block, lock() will not return until the lock is acquired. If block is cc_lock_noblock, lock() will return immediately, either acquiring the lock and returning ccNoError, or failing to acquire the lock and returning an error explaining why.

+To avoid having to deal with differences between thread semantics on different platforms, locks are granted per ccache, rather than per thread or per process. That means that different threads of execution have to acquire separate contexts in order to be able to synchronize with each other.

+The lock should be unlocked by using cc_ccache_unlock().

+

Note:
All locks are advisory. For example, callers which do not call cc_ccache_lock() and cc_ccache_unlock() will not be prevented from writing to the ccache when you have a read lock. This is because the CCAPI locking was added after the first release and thus adding mandatory locks would have changed the user experience and performance of existing applications.
+
+

+ + + + +
+ + + + +
cc_int32(* unlock)(cc_ccache_t io_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_unlock(): Unlock a ccache. +

+

Parameters:
+ + +
io_ccache a ccache object.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* get_last_default_time)(cc_ccache_t in_ccache, cc_time_t *out_last_default_time)
+
+ + + + + +
+   + + +

+cc_ccache_get_change_time(): Get the last time a ccache was the default ccache. +

+

Parameters:
+ + + +
in_ccache a cache object.
out_last_default_time on exit, the last time the ccache was default.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+This function returns the last time when the ccache was made the default ccache. This allows clients to sort the ccaches by how recently they were default, which is useful for user listing of ccaches. If the ccache was never default, ccErrNeverDefault is returned.
+

+ + + + +
+ + + + +
cc_int32(* get_change_time)(cc_ccache_t in_ccache, cc_time_t *out_change_time)
+
+ + + + + +
+   + + +

+cc_ccache_get_change_time(): Get the last time a ccache changed. +

+

Parameters:
+ + + +
in_ccache a cache object.
out_change_time on exit, the last time the ccache changed.
+
+
Returns:
On success, ccNoError. If the ccache was never the default ccache, ccErrNeverDefault. Otherwise, an error code representing the failure.
+This function returns the time of the most recent change made to a ccache. By maintaining a local copy the caller can deduce whether or not the ccache has been modified since the previous call to cc_ccache_get_change_time().

+The time returned by cc_ccache_get_change_time() increases whenever:

+

    +
  • a credential is stored
  • +
  • a credential is removed
  • +
  • a ccache principal is changed
  • +
  • the ccache becomes the default ccache
  • +
  • the ccache is no longer the default ccache
  • +
+
Note:
In order to be able to compare two values returned by cc_ccache_get_change_time(), the caller must use the same ccache object to acquire them. Callers should maintain a single ccache object in memory for cc_ccache_get_change_time() calls rather than creating a new ccache object for every call.
+
See also:
wait_for_change
+
+

+ + + + +
+ + + + +
cc_int32(* compare)(cc_ccache_t in_ccache, cc_ccache_t in_compare_to_ccache, cc_uint32 *out_equal)
+
+ + + + + +
+   + + +

+cc_ccache_compare(): Compare two ccache objects. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_compare_to_ccache a ccache object to compare with in_ccache.
out_equal on exit, whether or not the two ccaches refer to the same ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* get_kdc_time_offset)(cc_ccache_t in_ccache, cc_uint32 in_credentials_version, cc_time_t *out_time_offset)
+
+ + + + + +
+   + + +

+cc_ccache_get_kdc_time_offset(): Get the KDC time offset for credentials in a ccache. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_credentials_version the credentials version to get the time offset for.
out_time_offset on exit, the KDC time offset for in_ccache for credentials version in_credentials_version.
+
+
Returns:
On success, ccNoError if a time offset was obtained or ccErrTimeOffsetNotSet if a time offset has not been set. On failure, an error code representing the failure.
+
See also:
set_kdc_time_offset, clear_kdc_time_offset
+Sometimes the KDC and client's clocks get out of sync. cc_ccache_get_kdc_time_offset() returns the difference between the KDC and client's clocks at the time credentials were acquired. This offset allows callers to figure out how much time is left on a given credential even though the end_time is based on the KDC's clock not the client's clock.
+

+ + + + +
+ + + + +
cc_int32(* set_kdc_time_offset)(cc_ccache_t io_ccache, cc_uint32 in_credentials_version, cc_time_t in_time_offset)
+
+ + + + + +
+   + + +

+cc_ccache_set_kdc_time_offset(): Set the KDC time offset for credentials in a ccache. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_credentials_version the credentials version to get the time offset for.
in_time_offset the new KDC time offset for in_ccache for credentials version in_credentials_version.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
See also:
get_kdc_time_offset, clear_kdc_time_offset
+Sometimes the KDC and client's clocks get out of sync. cc_ccache_set_kdc_time_offset() sets the difference between the KDC and client's clocks at the time credentials were acquired. This offset allows callers to figure out how much time is left on a given credential even though the end_time is based on the KDC's clock not the client's clock.
+

+ + + + +
+ + + + +
cc_int32(* clear_kdc_time_offset)(cc_ccache_t io_ccache, cc_uint32 in_credentials_version)
+
+ + + + + +
+   + + +

+cc_ccache_clear_kdc_time_offset(): Clear the KDC time offset for credentials in a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
in_credentials_version the credentials version to get the time offset for.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
See also:
get_kdc_time_offset, set_kdc_time_offset
+Sometimes the KDC and client's clocks get out of sync. cc_ccache_clear_kdc_time_offset() clears the difference between the KDC and client's clocks at the time credentials were acquired. This offset allows callers to figure out how much time is left on a given credential even though the end_time is based on the KDC's clock not the client's clock.
+

+ + + + +
+ + + + +
cc_int32(* wait_for_change)(cc_ccache_t in_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_wait_for_change(): Wait for the next change to a ccache. +

+

Parameters:
+ + +
in_ccache a ccache object.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+This function blocks until the next change is made to the ccache referenced by in_ccache. By repeatedly calling cc_ccache_wait_for_change() from a worker thread the caller can effectively receive callbacks whenever the ccache changes. This is considerably more efficient than polling with cc_ccache_get_change_time().

+cc_ccache_wait_for_change() will return whenever:

+

    +
  • a credential is stored
  • +
  • a credential is removed
  • +
  • the ccache principal is changed
  • +
  • the ccache becomes the default ccache
  • +
  • the ccache is no longer the default ccache
  • +
+
Note:
In order to make sure that the caller doesn't miss any changes, cc_ccache_wait_for_change() always returns immediately after the first time it is called on a new ccache object. Callers must use the same ccache object for successive calls to cc_ccache_wait_for_change() rather than creating a new ccache object for every call.
+
See also:
get_change_time
+
+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__d.html b/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__d.html new file mode 100644 index 000000000..5e85ee2da --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__d.html @@ -0,0 +1,43 @@ + + +Credentials Cache API : cc_ccache_iterator_d Struct Reference + + + + +

cc_ccache_iterator_d Struct Reference
+ +[cc_ccache_iterator_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const cc_ccache_iterator_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__f.html b/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__f.html new file mode 100644 index 000000000..333aab8f4 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__ccache__iterator__f.html @@ -0,0 +1,117 @@ + + +Credentials Cache API : cc_ccache_iterator_f Struct Reference + + + + +

cc_ccache_iterator_f Struct Reference


Detailed Description

+Function pointer table for cc_ccache_iterator_t. For more information see cc_ccache_iterator_t Overview. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_ccache_iterator_t io_ccache_iterator)
+
+ + + + + +
+   + + +

+cc_ccache_iterator_release(): Release memory associated with a cc_ccache_iterator_t object. +

+

Parameters:
+ + +
io_ccache_iterator the ccache iterator object to release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* next)(cc_ccache_iterator_t in_ccache_iterator, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_ccache_iterator_next(): Get the next ccache in the cache collection. +

+

Parameters:
+ + + +
in_ccache_iterator a ccache iterator object.
out_ccache on exit, the next ccache in the cache collection.
+
+
Returns:
On success, ccNoError if the next ccache in the cache collection was obtained or ccIteratorEnd if there are no more ccaches. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* clone)(cc_ccache_iterator_t in_ccache_iterator, cc_ccache_iterator_t *out_ccache_iterator)
+
+ + + + + +
+   + + +

+cc_ccache_iterator_clone(): Make a copy of a ccache iterator. +

+

Parameters:
+ + + +
in_ccache_iterator a ccache iterator object.
out_ccache_iterator on exit, a copy of in_ccache_iterator.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__context__d.html b/krb5-1-7/doc/ccapi/html/structcc__context__d.html new file mode 100644 index 000000000..d3904a2a1 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__context__d.html @@ -0,0 +1,43 @@ + + +Credentials Cache API : cc_context_d Struct Reference + + + + +

cc_context_d Struct Reference
+ +[cc_context_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const cc_context_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__context__f.html b/krb5-1-7/doc/ccapi/html/structcc__context__f.html new file mode 100644 index 000000000..fe310518a --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__context__f.html @@ -0,0 +1,513 @@ + + +Credentials Cache API : cc_context_f Struct Reference + + + + +

cc_context_f Struct Reference


Detailed Description

+Function pointer table for cc_context_t. For more information see cc_context_t Overview. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_context_t io_context)
+
+ + + + + +
+   + + +

+cc_context_release(): Release memory associated with a cc_context_t. +

+

Parameters:
+ + +
io_context the context object to free.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* get_change_time)(cc_context_t in_context, cc_time_t *out_time)
+
+ + + + + +
+   + + +

+cc_context_get_change_time(): Get the last time the cache collection changed. +

+

Parameters:
+ + + +
in_context the context object for the cache collection to examine.
out_time on exit, the time of the most recent change for the entire ccache collection.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+This function returns the time of the most recent change for the entire ccache collection. By maintaining a local copy the caller can deduce whether or not the ccache collection has been modified since the previous call to cc_context_get_change_time().

+The time returned by cc_context_get_changed_time() increases whenever:

+

    +
  • a ccache is created
  • +
  • a ccache is destroyed
  • +
  • a credential is stored
  • +
  • a credential is removed
  • +
  • a ccache principal is changed
  • +
  • the default ccache is changed
  • +
+
Note:
In order to be able to compare two values returned by cc_context_get_change_time(), the caller must use the same context to acquire them. Callers should maintain a single context in memory for cc_context_get_change_time() calls rather than creating a new context for every call.
+
See also:
wait_for_change
+
+

+ + + + +
+ + + + +
cc_int32(* get_default_ccache_name)(cc_context_t in_context, cc_string_t *out_name)
+
+ + + + + +
+   + + +

+cc_context_get_default_ccache_name(): Get the name of the default ccache. +

+

Parameters:
+ + + +
in_context the context object for the cache collection.
out_name on exit, the name of the default ccache.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+This function returns the name of the default ccache. When the default ccache exists, its name is returned. If there are no ccaches in the collection, and thus there is no default ccache, the name that the default ccache should have is returned. The ccache with that name will be used as the default ccache by all processes which initialized Kerberos libraries before the ccache was created.

+If there is no default ccache, and the client is creating a new ccache, it should be created with the default name. If there already is a default ccache, and the client wants to create a new ccache (as opposed to reusing an existing ccache), it should be created with any unique name; create_new_ccache() can be used to accomplish that more easily.

+If the first ccache is created with a name other than the default name, then the processes already running will not notice the credentials stored in the new ccache, which is normally undesirable.

+

+ + + + +
+ + + + +
cc_int32(* open_ccache)(cc_context_t in_context, const char *in_name, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_context_open_ccache(): Open a ccache. +

+

Parameters:
+ + + + +
in_context the context object for the cache collection.
in_name the name of the ccache to open.
out_ccache on exit, a ccache object for the ccache
+
+
Returns:
On success, ccNoError. If no ccache named in_name exists, ccErrCCacheNotFound. On failure, an error code representing the failure.
+Opens an already existing ccache identified by its name. It returns a reference to the ccache in out_ccache.

+The list of all ccache names, principals, and credentials versions may be retrieved by calling cc_context_new_cache_iterator(), cc_ccache_get_name(), cc_ccache_get_principal(), and cc_ccache_get_cred_version().

+

+ + + + +
+ + + + +
cc_int32(* open_default_ccache)(cc_context_t in_context, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_context_open_default_ccache(): Open the default ccache. +

+

Parameters:
+ + + +
in_context the context object for the cache collection.
out_ccache on exit, a ccache object for the default ccache
+
+
Returns:
On success, ccNoError. If no default ccache exists, ccErrCCacheNotFound. On failure, an error code representing the failure.
+Opens the default ccache. It returns a reference to the ccache in *ccache.

+This function performs the same function as calling cc_context_get_default_ccache_name followed by cc_context_open_ccache, but it performs it atomically.

+

+ + + + +
+ + + + +
cc_int32(* create_ccache)(cc_context_t in_context, const char *in_name, cc_uint32 in_cred_vers, const char *in_principal, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_context_create_ccache(): Create a new ccache. +

+

Parameters:
+ + + + + + +
in_context the context object for the cache collection.
in_name the name of the new ccache to create
in_cred_vers the version of the credentials the new ccache will hold
in_principal the client principal of the credentials the new ccache will hold
out_ccache on exit, a ccache object for the newly created ccache
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Create a new credentials cache. The ccache is uniquely identified by its name. The principal given is also associated with the ccache and the credentials version specified. A NULL name is not allowed (and ccErrBadName is returned if one is passed in). Only cc_credentials_v4 and cc_credentials_v5 are valid input values for cred_vers. If you want to create a new ccache that will hold both versions of credentials, call cc_context_create_ccache() with one version, and then cc_ccache_set_principal() with the other version.

+If you want to create a new ccache (with a unique name), you should use cc_context_create_new_ccache() instead. If you want to create or reinitialize the default cache, you should use cc_context_create_default_ccache().

+If name is non-NULL and there is already a ccache named name:

+

    +
  • the credentials in the ccache whose version is cred_vers are removed
  • +
  • the principal (of the existing ccache) associated with cred_vers is set to principal
  • +
  • a handle for the existing ccache is returned and all existing handles for the ccache remain valid
  • +
+If no ccache named name already exists:

+

    +
  • a new empty ccache is created
  • +
  • the principal of the new ccache associated with cred_vers is set to principal
  • +
  • a handle for the new ccache is returned
  • +
+For a new ccache, the name should be any unique string. The name is not intended to be presented to users.

+If the created ccache is the first ccache in the collection, it is made the default ccache. Note that normally it is undesirable to create the first ccache with a name different from the default ccache name (as returned by cc_context_get_default_ccache_name()); see the description of cc_context_get_default_ccache_name() for details.

+The principal should be a C string containing an unparsed Kerberos principal in the format of the appropriate Kerberos version, i.e.

foo.bar/@BAZ 
+      * 
for Kerberos v4 and
foo/bar/@BAZ 
for Kerberos v5.
+

+ + + + +
+ + + + +
cc_int32(* create_default_ccache)(cc_context_t in_context, cc_uint32 in_cred_vers, const char *in_principal, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_context_create_default_ccache(): Create a new default ccache. +

+

Parameters:
+ + + + + +
in_context the context object for the cache collection.
in_cred_vers the version of the credentials the new default ccache will hold
in_principal the client principal of the credentials the new default ccache will hold
out_ccache on exit, a ccache object for the newly created default ccache
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Create the default credentials cache. The behavior of this function is similar to that of cc_create_ccache(). If there is a default ccache (which is always the case except when there are no ccaches at all in the collection), it is initialized with the specified credentials version and principal, as per cc_create_ccache(); otherwise, a new ccache is created, and its name is the name returned by cc_context_get_default_ccache_name().
+

+ + + + +
+ + + + +
cc_int32(* create_new_ccache)(cc_context_t in_context, cc_uint32 in_cred_vers, const char *in_principal, cc_ccache_t *out_ccache)
+
+ + + + + +
+   + + +

+cc_context_create_new_ccache(): Create a new uniquely named ccache. +

+

Parameters:
+ + + + + +
in_context the context object for the cache collection.
in_cred_vers the version of the credentials the new ccache will hold
in_principal the client principal of the credentials the new ccache will hold
out_ccache on exit, a ccache object for the newly created ccache
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Create a new unique credentials cache. The behavior of this function is similar to that of cc_create_ccache(). If there are no ccaches, and therefore no default ccache, the new ccache is created with the default ccache name as would be returned by get_default_ccache_name(). If there are some ccaches, and therefore there is a default ccache, the new ccache is created with a new unique name. Clearly, this function never reinitializes a ccache, since it always uses a unique name.
+

+ + + + +
+ + + + +
cc_int32(* new_ccache_iterator)(cc_context_t in_context, cc_ccache_iterator_t *out_iterator)
+
+ + + + + +
+   + + +

+cc_context_new_ccache_iterator(): Get an iterator for the cache collection. +

+

Parameters:
+ + + +
in_context the context object for the cache collection.
out_iterator on exit, a ccache iterator object for the ccache collection.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Used to allocate memory and initialize iterator. Successive calls to iterator's next() function will return ccaches in the collection.

+If changes are made to the collection while an iterator is being used on it, the iterator must return at least the intersection, and at most the union, of the set of ccaches that were present when the iteration began and the set of ccaches that are present when it ends.

+

+ + + + +
+ + + + +
cc_int32(* lock)(cc_context_t in_context, cc_uint32 in_lock_type, cc_uint32 in_block)
+
+ + + + + +
+   + + +

+cc_context_lock(): Lock the cache collection. +

+

Parameters:
+ + + + +
in_context the context object for the cache collection.
in_lock_type the type of lock to obtain.
in_block whether or not the function should block if the lock cannot be obtained immediately.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+Attempts to acquire an advisory lock for the ccache collection. Allowed values for lock_type are:

+

    +
  • cc_lock_read: a read lock.
  • +
  • cc_lock_write: a write lock
  • +
  • cc_lock_upgrade: upgrade an already-obtained read lock to a write lock
  • +
  • cc_lock_downgrade: downgrade an already-obtained write lock to a read lock
  • +
+If block is cc_lock_block, lock() will not return until the lock is acquired. If block is cc_lock_noblock, lock() will return immediately, either acquiring the lock and returning ccNoError, or failing to acquire the lock and returning an error explaining why.

+Locks apply only to the list of ccaches, not the contents of those ccaches. To prevent callers participating in the advisory locking from changing the credentials in a cache you must also lock that ccache with cc_ccache_lock(). This is so that you can get the list of ccaches without preventing applications from simultaneously obtaining service tickets.

+To avoid having to deal with differences between thread semantics on different platforms, locks are granted per context, rather than per thread or per process. That means that different threads of execution have to acquire separate contexts in order to be able to synchronize with each other.

+The lock should be unlocked by using cc_context_unlock().

+

Note:
All locks are advisory. For example, callers which do not call cc_context_lock() and cc_context_unlock() will not be prevented from writing to the cache collection when you have a read lock. This is because the CCAPI locking was added after the first release and thus adding mandatory locks would have changed the user experience and performance of existing applications.
+
+

+ + + + +
+ + + + +
cc_int32(* unlock)(cc_context_t in_cc_context)
+
+ + + + + +
+   + + +

+cc_context_unlock(): Unlock the cache collection. +

+

Parameters:
+ + +
in_context the context object for the cache collection.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* compare)(cc_context_t in_cc_context, cc_context_t in_compare_to_context, cc_uint32 *out_equal)
+
+ + + + + +
+   + + +

+cc_context_compare(): Compare two context objects. +

+

Parameters:
+ + + + +
in_context a context object.
in_compare_to_context a context object to compare with in_context.
out_equal on exit, whether or not the two contexts refer to the same cache collection.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* wait_for_change)(cc_context_t in_cc_context)
+
+ + + + + +
+   + + +

+cc_context_wait_for_change(): Wait for the next change in the cache collection. +

+

Parameters:
+ + +
in_context a context object.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+This function blocks until the next change is made to the cache collection ccache collection. By repeatedly calling cc_context_wait_for_change() from a worker thread the caller can effectively receive callbacks whenever the cache collection changes. This is considerably more efficient than polling with cc_context_get_change_time().

+cc_context_wait_for_change() will return whenever:

+

    +
  • a ccache is created
  • +
  • a ccache is destroyed
  • +
  • a credential is stored
  • +
  • a credential is removed
  • +
  • a ccache principal is changed
  • +
  • the default ccache is changed
  • +
+
Note:
In order to make sure that the caller doesn't miss any changes, cc_context_wait_for_change() always returns immediately after the first time it is called on a new context object. Callers must use the same context object for successive calls to cc_context_wait_for_change() rather than creating a new context for every call.
+
See also:
get_change_time
+
+


Generated on Tue Oct 2 17:16:05 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__d.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__d.html new file mode 100644 index 000000000..8a13251e5 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__d.html @@ -0,0 +1,67 @@ + + +Credentials Cache API : cc_credentials_d Struct Reference + + + + +

cc_credentials_d Struct Reference
+ +[cc_credentials_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const cc_credentials_union* data
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
const cc_credentials_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__f.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__f.html new file mode 100644 index 000000000..91f4b3adb --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__f.html @@ -0,0 +1,85 @@ + + +Credentials Cache API : cc_credentials_f Struct Reference + + + + +

cc_credentials_f Struct Reference


Detailed Description

+Function pointer table for cc_credentials_t. For more information see cc_credentials_t Overview. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_credentials_t io_credentials)
+
+ + + + + +
+   + + +

+cc_credentials_release(): Release memory associated with a cc_credentials_t object. +

+

Parameters:
+ + +
io_credentials the credentials object to release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* compare)(cc_credentials_t in_credentials, cc_credentials_t in_compare_to_credentials, cc_uint32 *out_equal)
+
+ + + + + +
+   + + +

+cc_credentials_compare(): Compare two credentials objects. +

+

Parameters:
+ + + + +
in_credentials a credentials object.
in_compare_to_credentials a credentials object to compare with in_credentials.
out_equal on exit, whether or not the two credentials objects refer to the same credentials in the cache collection.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__d.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__d.html new file mode 100644 index 000000000..5682db0ed --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__d.html @@ -0,0 +1,43 @@ + + +Credentials Cache API : cc_credentials_iterator_d Struct Reference + + + + +

cc_credentials_iterator_d Struct Reference
+ +[cc_credentials_iterator_t] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const cc_credentials_iterator_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__f.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__f.html new file mode 100644 index 000000000..66aec178a --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__iterator__f.html @@ -0,0 +1,85 @@ + + +Credentials Cache API : cc_credentials_iterator_f Struct Reference + + + + +

cc_credentials_iterator_f Struct Reference


Detailed Description

+Function pointer table for cc_credentials_iterator_t. For more information see cc_credentials_iterator_t. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_credentials_iterator_t io_credentials_iterator)
+
+ + + + + +
+   + + +

+cc_credentials_iterator_release(): Release memory associated with a cc_credentials_iterator_t object. +

+

Parameters:
+ + +
io_credentials_iterator the credentials iterator object to release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+

+ + + + +
+ + + + +
cc_int32(* next)(cc_credentials_iterator_t in_credentials_iterator, cc_credentials_t *out_credentials)
+
+ + + + + +
+   + + +

+cc_credentials_iterator_next(): Get the next credentials in the ccache. +

+

Parameters:
+ + + +
in_credentials_iterator a credentials iterator object.
out_credentials on exit, the next credentials in the ccache.
+
+
Returns:
On success, ccNoError if the next credential in the ccache was obtained or ccIteratorEnd if there are no more credentials. On failure, an error code representing the failure.
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__union.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__union.html new file mode 100644 index 000000000..6082346cc --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__union.html @@ -0,0 +1,118 @@ + + +Credentials Cache API : cc_credentials_union Struct Reference + + + + +

cc_credentials_union Struct Reference
+ +[cc_credentials_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_uint32 version
+
+ + + + + +
+   + + +

+The credentials version of this credentials object.

+

+ + + + +
+ + + + +
cc_credentials_v4_t* credentials_v4
+
+ + + + + +
+   + + +

+If version is cc_credentials_v4, a pointer to a cc_credentials_v4_t.

+

+ + + + +
+ + + + +
cc_credentials_v5_t* credentials_v5
+
+ + + + + +
+   + + +

+If version is cc_credentials_v5, a pointer to a cc_credentials_v5_t.

+

+ + + + +
+ + + + +
union { ... } credentials
+
+ + + + + +
+   + + +

+The credentials.

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__v4__t.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__v4__t.html new file mode 100644 index 000000000..086e7fea7 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__v4__t.html @@ -0,0 +1,358 @@ + + +Credentials Cache API : cc_credentials_v4_t Struct Reference + + + + +

cc_credentials_v4_t Struct Reference
+ +[cc_credentials_t Overview] +


Detailed Description

+If a cc_credentials_t variable is used to store Kerberos v4 credentials, then credentials.credentials_v4 points to a v4 credentials structure. This structure is similar to a krb4 API CREDENTIALS structure. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_uint32 version
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
char principal[cc_v4_name_size]
+
+ + + + + +
+   + + +

+A properly quoted string representation of the first component of the client principal

+

+ + + + +
+ + + + +
char principal_instance[cc_v4_instance_size]
+
+ + + + + +
+   + + +

+A properly quoted string representation of the second component of the client principal

+

+ + + + +
+ + + + +
char service[cc_v4_name_size]
+
+ + + + + +
+   + + +

+A properly quoted string representation of the first component of the service principal

+

+ + + + +
+ + + + +
char service_instance[cc_v4_instance_size]
+
+ + + + + +
+   + + +

+A properly quoted string representation of the second component of the service principal

+

+ + + + +
+ + + + +
char realm[cc_v4_realm_size]
+
+ + + + + +
+   + + +

+A properly quoted string representation of the realm

+

+ + + + +
+ + + + +
unsigned char session_key[cc_v4_key_size]
+
+ + + + + +
+   + + +

+Ticket session key

+

+ + + + +
+ + + + +
cc_int32 kvno
+
+ + + + + +
+   + + +

+Key version number

+

+ + + + +
+ + + + +
cc_int32 string_to_key_type
+
+ + + + + +
+   + + +

+String to key type used. See cc_string_to_key_type for valid values

+

+ + + + +
+ + + + +
cc_time_t issue_date
+
+ + + + + +
+   + + +

+Time when the ticket was issued

+

+ + + + +
+ + + + +
cc_int32 lifetime
+
+ + + + + +
+   + + +

+Ticket lifetime in 5 minute units

+

+ + + + +
+ + + + +
cc_uint32 address
+
+ + + + + +
+   + + +

+IPv4 address of the client the ticket was issued for

+

+ + + + +
+ + + + +
cc_int32 ticket_size
+
+ + + + + +
+   + + +

+Ticket size (no greater than cc_v4_ticket_size)

+

+ + + + +
+ + + + +
unsigned char ticket[cc_v4_ticket_size]
+
+ + + + + +
+   + + +

+Ticket data

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__credentials__v5__t.html b/krb5-1-7/doc/ccapi/html/structcc__credentials__v5__t.html new file mode 100644 index 000000000..ad0996281 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__credentials__v5__t.html @@ -0,0 +1,334 @@ + + +Credentials Cache API : cc_credentials_v5_t Struct Reference + + + + +

cc_credentials_v5_t Struct Reference
+ +[cc_credentials_t Overview] +


Detailed Description

+If a cc_credentials_t variable is used to store Kerberos v5 c redentials, and then credentials.credentials_v5 points to a v5 credentials structure. This structure is similar to a krb5_creds structure. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
char* client
+
+ + + + + +
+   + + +

+A properly quoted string representation of the client principal.

+

+ + + + +
+ + + + +
char* server
+
+ + + + + +
+   + + +

+A properly quoted string representation of the service principal.

+

+ + + + +
+ + + + +
cc_data keyblock
+
+ + + + + +
+   + + +

+Session encryption key info.

+

+ + + + +
+ + + + +
cc_time_t authtime
+
+ + + + + +
+   + + +

+The time when the ticket was issued.

+

+ + + + +
+ + + + +
cc_time_t starttime
+
+ + + + + +
+   + + +

+The time when the ticket becomes valid.

+

+ + + + +
+ + + + +
cc_time_t endtime
+
+ + + + + +
+   + + +

+The time when the ticket expires.

+

+ + + + +
+ + + + +
cc_time_t renew_till
+
+ + + + + +
+   + + +

+The time when the ticket becomes no longer renewable (if renewable).

+

+ + + + +
+ + + + +
cc_uint32 is_skey
+
+ + + + + +
+   + + +

+1 if the ticket is encrypted in another ticket's key, or 0 otherwise.

+

+ + + + +
+ + + + +
cc_uint32 ticket_flags
+
+ + + + + +
+   + + +

+Ticket flags, as defined by the Kerberos 5 API.

+

+ + + + +
+ + + + +
cc_data** addresses
+
+ + + + + +
+   + + +

+The the list of network addresses of hosts that are allowed to authenticate using this ticket.

+

+ + + + +
+ + + + +
cc_data ticket
+
+ + + + + +
+   + + +

+Ticket data.

+

+ + + + +
+ + + + +
cc_data second_ticket
+
+ + + + + +
+   + + +

+Second ticket data.

+

+ + + + +
+ + + + +
cc_data** authdata
+
+ + + + + +
+   + + +

+Authorization data.

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__data.html b/krb5-1-7/doc/ccapi/html/structcc__data.html new file mode 100644 index 000000000..346f6a41d --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__data.html @@ -0,0 +1,94 @@ + + +Credentials Cache API : cc_data Struct Reference + + + + +

cc_data Struct Reference
+ +[cc_credentials_t Overview] +


Detailed Description

+The CCAPI data structure. This structure is similar to a krb5_data structure. In a v5 credentials structure, cc_data structures are used to store tagged variable-length binary data. Specifically, for cc_credentials_v5.ticket and cc_credentials_v5.second_ticket, the cc_data.type field must be zero. For the cc_credentials_v5.addresses, cc_credentials_v5.authdata, and cc_credentials_v5.keyblock, the cc_data.type field should be the address type, authorization data type, and encryption type, as defined by the Kerberos v5 protocol definition. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_uint32 type
+
+ + + + + +
+   + + +

+The type of the data as defined by the krb5_data structure.

+

+ + + + +
+ + + + +
cc_uint32 length
+
+ + + + + +
+   + + +

+The length of data.

+

+ + + + +
+ + + + +
void* data
+
+ + + + + +
+   + + +

+The data buffer.

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__string__d.html b/krb5-1-7/doc/ccapi/html/structcc__string__d.html new file mode 100644 index 000000000..b38286b3e --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__string__d.html @@ -0,0 +1,67 @@ + + +Credentials Cache API : cc_string_d Struct Reference + + + + +

cc_string_d Struct Reference
+ +[cc_string_t Overview] +

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
const char* data
+
+ + + + + +
+   + + +

+

+

+ + + + +
+ + + + +
const cc_string_f* functions
+
+ + + + + +
+   + + +

+

+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/ccapi/html/structcc__string__f.html b/krb5-1-7/doc/ccapi/html/structcc__string__f.html new file mode 100644 index 000000000..d5f738f49 --- /dev/null +++ b/krb5-1-7/doc/ccapi/html/structcc__string__f.html @@ -0,0 +1,51 @@ + + +Credentials Cache API : cc_string_f Struct Reference + + + + +

cc_string_f Struct Reference


Detailed Description

+Function pointer table for cc_string_t. For more information see cc_string_t Overview. +

+

Data Fields

+ +

Field Documentation

+

+ + + + +
+ + + + +
cc_int32(* release)(cc_string_t io_string)
+
+ + + + + +
+   + + +

+cc_string_release(): Release memory associated with a cc_string_t object. +

+

Parameters:
+ + +
io_string the string object to release.
+
+
Returns:
On success, ccNoError. On failure, an error code representing the failure.
+
+


Generated on Tue Oct 2 17:16:06 2007 for Credentials Cache API by  + +doxygen 1.4.6
+ + diff --git a/krb5-1-7/doc/coding-style b/krb5-1-7/doc/coding-style new file mode 100644 index 000000000..e4c99967a --- /dev/null +++ b/krb5-1-7/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-7/doc/contributing.txt b/krb5-1-7/doc/contributing.txt new file mode 100644 index 000000000..776c5d58d --- /dev/null +++ b/krb5-1-7/doc/contributing.txt @@ -0,0 +1,70 @@ + Contributing to MIT Kerberos + +DESIGN +====== + +If you are planning to contribute a substantial amount of work, please +ensure that you have a discussion about the design on the +krbdev@mit.edu list. Some changes may require coordination with +standards groups. For example, interface changes and extensions for +the GSS-API should be discussed in the IETF KITTEN Working Group. + +STYLE +===== + +Please follow the guidelines in doc/coding-style for new code. For +existing code, please preserve its existing indentation and brace +conventions. These existing conventions usually resemble the +guidelines in doc/coding-style. Exceptions to the style in +doc/coding-style are usually large past contributions or imports from +other parties. These include (not an exhaustive list): + + src/appl/bsd + src/appl/gssftp + src/appl/telnet + src/kadmin + src/lib/kadm5 + src/lib/gssapi/mechglue + src/lib/rpc + +PATCHES +======= + +We prefer patches in either unified or context diff format (diff -u or +diff -c). As is usual practice, please specify the original file +before the modified file on the diff command line. It's also useful +to perform the diff from the top level of the tree, e.g., + + diff -ur src.orig src + +It's even more useful if you use our anonymous Subversion repository +at + + svn://anonsvn.mit.edu/krb5 + +and use "svn diff" (or "svk diff" if you prefer to use SVK) to +generate your patches. + +It is much easier for us to integrate patches which are generated +against current code on the trunk. Please ensure that your source +tree is up-to-date before generating your patch. + +COPYRIGHT +========= + +If you are submitting substantial quantities of new code, or are +substantially modifying existing code, please be clear about the +copyright status of your contributions. Note that if your +contribution was created in the course of your employment, your +employer may own copyright in your contribution. + +We prefer that MIT receives the ownership of the contributions, but +will generally accept contributed code with copyright owned by other +parties provided that the license conditions are substantially +identical to the existing license on the MIT krb5 code. + +Appropriate copyright notices and license terms should be added to new +or changed files, unless the contributed code is being assigned to the +already-listed copyright holder in the file, or the contribution is +being released to the public domain. Please make sure that the +year in the copyright statement is kept up-to-date. diff --git a/krb5-1-7/doc/copyright.texinfo b/krb5-1-7/doc/copyright.texinfo new file mode 100644 index 000000000..018c41043 --- /dev/null +++ b/krb5-1-7/doc/copyright.texinfo @@ -0,0 +1,721 @@ +Copyright @copyright{} 1985-2009 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 + +and the initial implementation of incremental propagation, including +the following new or changed files: + +@smallexample + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + slave/kpropd_rpc.c + slave/kproplog.c +@end smallexample + +and marked portions of the following files: + +@smallexample + lib/krb5/os/hst_realm.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 @copyright{} 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 + +Portions contributed by Apple Inc. are subject to the following license: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +Copyright 2004-2008 Apple Inc. All Rights Reserved. + +Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of Apple Inc. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Apple Inc. 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. + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex +@end quotation + +The implementations of strlcpy and strlcat in +src/util/support/strlcat.c have the following copyright and permission +notice: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +Copyright @copyright{} 1998 Todd C. Miller + +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 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. + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex +@end quotation + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +The OpenLDAP Public License + Version 2.8, 17 August 2003 + +Redistribution and use of this software and associated documentation +("Software"), with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions in source form must retain copyright statements + and notices, + +2. Redistributions in binary form must reproduce applicable copyright + statements and notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution, and + +3. Redistributions must contain a verbatim copy of this document. + +The OpenLDAP Foundation may revise this license from time to time. +Each revision is distinguished by a version number. You may use +this Software under terms of this license revision or under the +terms of any subsequent revision of the license. + +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS +CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) +OR OWNER(S) OF THE SOFTWARE 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 names of the authors and copyright holders must not be used in +advertising or otherwise to promote the sale, use or other dealing +in this Software without specific, written prior permission. Title +to copyright in this Software shall at all times remain with copyright +holders. + +OpenLDAP is a registered trademark of the OpenLDAP Foundation. + +Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, +California, USA. All Rights Reserved. Permission to copy and +distribute verbatim copies of this document is granted. + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex +@end quotation + +Marked test programs in src/lib/krb5/krb have the following copyright: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +Copyright @copyright{} 2006 Kungliga Tekniska H@"{o}gskolan +(Royal Institute of Technology, Stockholm, Sweden). +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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. + +@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-7/doc/definitions.texinfo b/krb5-1-7/doc/definitions.texinfo new file mode 100644 index 000000000..e7f47b07d --- /dev/null +++ b/krb5-1-7/doc/definitions.texinfo @@ -0,0 +1,174 @@ +@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.7 +@set PREVRELEASE 1.6 +@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 aes128-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/osconf.hin +@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 24 hours +@comment max_life +@set DefaultMaxRenewableLife 0 +@comment max_rlife +@set DefaultDefaultPrincipalExpiration 0 +@comment expiration +@set DefaultSupportedEnctypes aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal arcfour-hmac-md5:normal +@comment krb5/src/include/osconf.hin, KRB5_DEFAULT_SUPPORTED_ENCTYPES + +@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 DefaultKrbRunAklog false +@comment login_krb_run_aklog +@set DefaultAklogPath $(prefix)/bin/aklog +@comment lines 955-956 +@set DefaultAcceptPasswd false +@comment login_accept_password + +@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 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-7/doc/dnssrv.texinfo b/krb5-1-7/doc/dnssrv.texinfo new file mode 100644 index 000000000..1a401ac14 --- /dev/null +++ b/krb5-1-7/doc/dnssrv.texinfo @@ -0,0 +1,93 @@ +@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. + +@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-7/doc/dnstxt.texinfo b/krb5-1-7/doc/dnstxt.texinfo new file mode 100644 index 000000000..e06d220cf --- /dev/null +++ b/krb5-1-7/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-7/doc/document-list.texinfo b/krb5-1-7/doc/document-list.texinfo new file mode 100644 index 000000000..65058b96d --- /dev/null +++ b/krb5-1-7/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-7/doc/glossary.texinfo b/krb5-1-7/doc/glossary.texinfo new file mode 100644 index 000000000..d49a56a7f --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/Makefile b/krb5-1-7/doc/implement/Makefile new file mode 100644 index 000000000..4c5116132 --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/ccache-i.tex b/krb5-1-7/doc/implement/ccache-i.tex new file mode 100644 index 000000000..66d7b61bf --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/cksum-i.tex b/krb5-1-7/doc/implement/cksum-i.tex new file mode 100644 index 000000000..c7f763738 --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/crc-32-i.tex b/krb5-1-7/doc/implement/crc-32-i.tex new file mode 100644 index 000000000..c5d07a33d --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/encrypt-i.tex b/krb5-1-7/doc/implement/encrypt-i.tex new file mode 100644 index 000000000..57e8c833a --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/fancyheadings.sty b/krb5-1-7/doc/implement/fancyheadings.sty new file mode 100644 index 000000000..a71de0fb5 --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/fixunder.sty b/krb5-1-7/doc/implement/fixunder.sty new file mode 100644 index 000000000..b7ae58dbf --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/functions.sty b/krb5-1-7/doc/implement/functions.sty new file mode 100644 index 000000000..a3165f811 --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/implement.tex b/krb5-1-7/doc/implement/implement.tex new file mode 100644 index 000000000..7b709f56f --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/kdb-i.tex b/krb5-1-7/doc/implement/kdb-i.tex new file mode 100644 index 000000000..dc81971bb --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/keytab-i.tex b/krb5-1-7/doc/implement/keytab-i.tex new file mode 100644 index 000000000..697728721 --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/libos-i.tex b/krb5-1-7/doc/implement/libos-i.tex new file mode 100644 index 000000000..cdd4861ff --- /dev/null +++ b/krb5-1-7/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-7/doc/implement/rcache-i.tex b/krb5-1-7/doc/implement/rcache-i.tex new file mode 100644 index 000000000..e00a639da --- /dev/null +++ b/krb5-1-7/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-7/doc/implementor.texinfo b/krb5-1-7/doc/implementor.texinfo new file mode 100644 index 000000000..7f71195c5 --- /dev/null +++ b/krb5-1-7/doc/implementor.texinfo @@ -0,0 +1,1247 @@ +\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. + +Inline functions should always be specified in the code as +@code{static inline}, as the behavior of other forms vary across GCC +versions and C and C++ language standards. We assume that static +copies of inline functions will not be generated if they are not +needed; under some compilers that behave otherwise (such as the +current Sun compiler as of this writing) may produce executables and +libraries much larger than they need to be. + +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) + +Some of our code uses the SUSv2/C99 functions @code{snprintf} and +@code{vsnprintf}. Since the two specifications differ, we assume that +either specification may be followed: If truncation occurs, the return +value may be the untruncated output length, or it may be negative (or +may be zero if a zero length was supplied). It is therefore not +permitted in our code to call these functions with a zero output +length in order to determine the desired buffer size. A NULL output +pointer is not permitted. In the header @file{k5-platform.h} we +provide inline definitions for some platforms where these functions do +not exist. + +We also use the extension functions @code{asprintf} and +@code{vasprintf}, available on modern GNU and BSD based systems. The +behaviors of these functions on errors vary between the two system +types -- BSD stores a NULL as the output pointer, and GNU doesn't set +it. We assume either may be the case: The output pointer may be +unchanged or may be overwritten with NULL, and our code should thus +assume it may be garbage, and should be assigned to if the value +matters after an error is detected. Again, @file{k5-platform.h} +provides workarounds for systems where these functions are not +defined. + +Using these functions instead of plain @code{sprintf} without length +checking may make our code slightly less vulnerable to buffer +overruns. + +If necessary, we may eventually use a @code{[v]asnprintf} interface +like that of the GNU C library, but we have not done so yet. Do not +write code using that interface. + +@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 @code{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:: +* ELF 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, ELF 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.... [What?? This +never got finished!] + +@node ELF Shared Library Support, , Alpha OSF/1 Shared Library Support, Operating System Notes for Shared Libraries +@subsection ELF Shared Library Support + +It's tempting to add @samp{-Bsymbolic} to the commands for generating +shared libraries. We don't explicitly support overriding our +(internal or public) symbol names by applications, and binding at +shared library creation time would result in smaller libraries that +would load faster. However, it won't work. At least with the GNU and +Solaris linkers and runtime environments, an executable using a data +symbol exported by a shared library gets a copy of that data, +initialized at run time by copying, and the program will only function +properly if that definition can override the one present in the shared +library. And, sadly, some of our shared libraries export variables +that are directly referenced from programs. + +@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-7/doc/install-old.texi b/krb5-1-7/doc/install-old.texi new file mode 100644 index 000000000..af84a023e --- /dev/null +++ b/krb5-1-7/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-7/doc/install.texinfo b/krb5-1-7/doc/install.texinfo new file mode 100644 index 000000000..f9c682f5f --- /dev/null +++ b/krb5-1-7/doc/install.texinfo @@ -0,0 +1,1563 @@ +\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. +@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:: +* Incremental Database Propagation:: +@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, Incremental Database Propagation, 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 Incremental Database Propagation, , Switching Master and Slave KDCs, Installing KDCs +@subsection Incremental Database Propagation + +At some very large sites, dumping and transmitting the database can +take more time than is desirable for changes to propagate from the +master KDC to the slave KDCs. The incremental propagation support +added in the 1.7 release is intended to address this. + +With incremental propagation enabled, all programs on the master KDC +that change the database also write information about the changes to +an ``update log'' file, maintained as a circular buffer of a certain +size. A process on each slave KDC connects to a service on the master +KDC (currently implmented in the @code{kadmind} server) and +periodically requests the changes that have been made since the last +check. By default, this check is done every two minutes. If the +database has just been modified in the previous several seconds +(currently the threshold is hard-coded at 10 seconds), the slave will +not retrieve updates, but instead will pause and try again soon after. +This reduces the likelihood that incremental update queries will cause +delays for an administrator trying to make a bunch of changes to the +database at the same time. + +Incremental propagation uses the following entries in the per-realm +data in the KDC config file: + +@table @asis +@item @code{iprop_enable} (boolean) +If this is set to @code{true}, then incremental propagation is +enabled, and (as noted below) normal @code{kprop} propagation is +disabled. The default is @code{false}. + +@item @code{iprop_master_ulogsize} (integer) +This indicates the number of entries that should be retained in the +update log. The default is 1000; the maximum number is 2500. + +@item @code{iprop_slave_poll} (time interval) +This indicates how often the slave should poll the master KDC for +changes to the database. The default is two minutes. + +@item @code{iprop_port} (integer) +This specifies the port number to be used for incremental +propagation. This is required in both master and slave configuration +files. + +@item @code{iprop_logfile} (file name) +This specifies where the update log file for the realm database is to +be stored. The default is to use the @code{database_name} entry from +the @code{realms} section of the config file, with @file{.ulog} appended. +(NOTE: If @code{database_name} isn't specified in the @code{realms} +section, perhaps because the LDAP database back end is being used, or +the file name is specified in the @code{dbmodules} section, then the +hard-coded default for @code{database_name} is used. Determination of +the @code{iprop_logfile} default value will not use values from the +@code{dbmodules} section.) +@end table + +Both master and slave sides must have principals named +@code{kiprop/@var{hostname}} (where @var{hostname} is, as usual, the +lower-case, fully-qualified, canonical name for the host) registered +and keys stored in the default keytab file (@file{/etc/krb5.keytab}). +@c XXX: I think the master side, at least, might be able to read the +@c key out of the database. Test and document this. + +On the master KDC side, the @code{kiprop/@var{hostname}} principal +must be listed in the @code{kadmind} ACL file @code{kadm5.acl}, and +given the @code{p} privilege. + +On the slave KDC side, @code{kpropd} should be run. When incremental +propagation is enabled, it will connect to the @code{kadmind} on the +master KDC and start requesting updates. + +The normal @code{kprop} mechanism is disabled by the incremental +propagation support. However, if the slave has been unable to fetch +changes from the master KDC for too long (network problems, perhaps), +the log on the master may wrap around and overwrite some of the +updates that the slave has not yet retrieved. In this case, the slave +will instruct the master KDC to dump the current database out to a +file and invoke a one-time @code{kprop} propagation, with special +options to also convey the point in the update log at which the slave +should resume fetching incremental updates. Thus, all the keytab and +ACL setup previously described for @code{kprop} propagation is still +needed. + +There are several known bugs and restrictions in the current +implementation: +@itemize +@item +The ``call out to @code{kprop}'' mechanism is a bit fragile; if the +@code{kprop} propagation fails to connect for some reason, the process +on the slave may hang waiting for it, and will need to be restarted. +@item +The master and slave must be able to initiate TCP connections in both +directions, without an intervening NAT. They must also be able to +communicate over IPv4, since MIT's kprop and RPC code does not +currently support IPv6. +@end itemize + +@menu +* Sun/MIT Incremental Propagation Differences:: +@end menu + +@node Sun/MIT Incremental Propagation Differences, , Incremental Database Propagation, Incremental Database Propagation +@subsubsection Sun/MIT Incremental Propagation Differences + +Sun donated the original code for supporting incremental database +propagation to MIT. Some changes have been made in the MIT source +tree that will be visible to administrators. (These notes are based +on Sun's patches. Changes to Sun's implementation since then may not +be reflected here.) + +The Sun config file support looks for @code{sunw_dbprop_enable}, +@code{sunw_dbprop_master_ulogsize}, and @code{sunw_dbprop_slave_poll}. + +The incremental propagation service is implemented as an ONC RPC +service. In the Sun implementation, the service is registered with +@code{rpcbind} (also known as @code{portmapper}) and the client looks +up the port number to contact. In the MIT implementation, where +interaction with some modern versions of @code{rpcbind} doesn't always +work well, the port number must be specified in the config file on +both the master and slave sides. + +The Sun implementation hard-codes pathnames in @file{/var/krb5} for +the update log and the per-slave @code{kprop} dump files. In the MIT +implementation, the pathname for the update log is specified in the +config file, and the per-slave dump files are stored in +@code{@value{ROOTDIR}/var/krb5kdc/slave_datatrans_@var{hostname}}. + +@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 +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 + +@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-7/doc/iprop-notes.txt b/krb5-1-7/doc/iprop-notes.txt new file mode 100644 index 000000000..8efee36f6 --- /dev/null +++ b/krb5-1-7/doc/iprop-notes.txt @@ -0,0 +1,140 @@ +Some (intentional) changes from Sun's submission are noted in the +install guide. + +Bugs or issues: + +The "full resync" part of the protocol involves the master side firing +off a normal kprop (and going back to servicing requests), and the +slave side stopping all the incremental propagation stuff and waiting +for the kprop. If the connection from the master never comes in for +some reason, the slave side just blocks forever, and never resumes +incremental propagation. + +The protocol does not currently pass policy database changes; this was +an intentional decision on Sun's part. The policy database is only +relevant to the master KDC, and is usually fairly static (aside from +refcount updates), but not propagating it does mean that a slave +maintained via iprop can't simply be promoted to a master in disaster +recovery or other cases without doing a full propagation or restoring +a database from backups. + +Shawn had a good suggestion after I started the integration work, and +which I haven't had a chance to implement: Make the update-log code +fit in as a sort of pseudo-database layer via the DAL, being called +through the standard DAL methods, and doing its work around calls +through to the real database back end again through the DAL methods. +So for example, creating a "iprop+db2" database would create an update +log and the real db2 database; storing a principal entry would update +the update log as well; etc. At least initially, we wouldn't treat it +as a differently-named database; the installation of the hooks would +be done by explicitly checking if iprop is enabled, etc. + +The "iprop role" is assumed to be either master or slave. The master +writes a log, and the slave fetches it. But what about a cascade +propagation model where A sends to B which sends to C, perhaps because +A's bandwidth is highly limited, or B and C are co-located? In such a +case, B would want to operate in both modes. Granted, with iprop the +bandwidth issues should be less important, but there may still be +reasons one may wish to run in such a configuration. + +The propagation of changes does not happen in real time. It's not a +"push" protocol; the slaves poll periodically for changes. Perhaps a +future revision of the protocol could address that. + +kadmin/cli/kadmin.c call to kadm5_init_iprop - is this needed in +client-side program? Should it be done in libkadm5srv instead as part +of the existing kadm5_init* so that database-accessing applications +that don't get updated at the source level will automatically start +changing the update log as needed? + +Locking: Currently DAL exports the DB locking interface to the caller; +we want to slip the iprop code in between -- run it plus the DB update +operation with the DB lock held, whether or not the caller grabbed the +lock. (Does the caller always grab the lock before making changes?) +Currently we're using a file lock on the update log itself; this will +be independent of whether the DB back end implements locking (which +may be a good thing or a bad thing, depending). + +Various logging calls with odd format strings like "" should be +fixed. + +Why are different principal names used, when incremental propagation +requires that normal kprop (which uses host principals) be possible +anyways? + +Why is this tied to kadmind, aside from (a) wanting to prevent other +db changes, which locking protocols should deal with anyways, (b) +existing acl code, (c) existing server process? + +The incremental propagation protocol requires an ACL entry on the +master, listing the slave. Since the full-resync part uses normal +kprop, the slave also has to have an ACL entry for the master. If +this is missing, I suspect the behavior will be that every two +minutes, the master side will (at the prompting of the slave) dump out +the database and attempt a full propagation. + +Possible optimizations: If an existing dump file has a recent enough +serial number, just send it, without dumping again? Use just one dump +file instead of one per slave? + +Requiring normal kprop means the slave still can't be behind a NAT or +firewall without special configuration. The incremental parts can +work in such a configuration, so long as outgoing TCP connections are +allowed. + +Still limited to IPv4 because of limitations in MIT's version of the +RPC code. (This could be fixed for kprop, if IPv6 sites want to do +full propagation only. Doing incremental propagation over IPv6 will +take work on the RPC library, and probably introduce +backwards-incompatible ABI changes.) + +Overflow checks for ulogentries times block size? + +If file can't be made the size indicated by ulogentries, shoud we +truncate or error out? If we error out, this could blow out when +resizing the log because of a too-large log entry. + +The kprop invocation doesn't specify a realm name, so it'll only work +for the default realm. No clean way to specify a port number, either. +Would it be overkill to come up with a way to configure host+port for +kpropd on the master? Preferably in a way that'd support cascading +propagations. + +The kadmind process, when it needs to run kprop, extracts the slave +host name from the client principal name. It assumes that the +principal name will be of the form foo/hostname@REALM, and looks +specifically for the "/" and "@" to chop up the string form of the +name. If looking up that name won't give a working IPv4 address for +the slave, kprop will fail (and kpropd will keep waiting, incremental +updates will stop, etc). + +Mapping between file offsets and structure addresses, we should be +careful about alignment. We're probably okay on current platforms, +but if we break log-format compatibility with Sun at some point, use +the chance to make the kdb_ent_header_t offsets be more strictly +aligned in the file. (16 or 32 bytes?) + +Not thread safe! The kdb5.c code will get a lock on the update log +file while making changes, but the lock is per-process. Currently +there are no processes I know of that use multiple threads and change +the database. (There's the Novell patch to make the KDC +multithreaded, but the kdc-kdb-update option doesn't currently +compile.) + +Logging in kpropd is poor to useless. If there are any problems, run +it in debug mode ("-d"). You'll still lose all output from the +invocation of kdb5_util dump and kprop run out of kadmind. + +Other man page updates needed: Anything with new -x options. + +Comments from lha: + +Verify both client and server are demanding privacy from RPC. + +Authorization code in check_iprop_rpcsec_auth is weird. Check realm +checking, is it trusting the client realm length? + +What will happen if my realm is named "A" and I can get a cross realm +(though multihop) to ATHENA.MIT.EDU's iprop server? + +Why is the ACL not applied before we get to the functions themselves? diff --git a/krb5-1-7/doc/kadm5-errmsg.txt b/krb5-1-7/doc/kadm5-errmsg.txt new file mode 100644 index 000000000..76404bcaa --- /dev/null +++ b/krb5-1-7/doc/kadm5-errmsg.txt @@ -0,0 +1,59 @@ +Proposed approach for passing more detailed error messages across the +kadm5 API: + +We've already got too many init functions and too many options. +Multiplying the number of init functions isn't feasible. + +Create an (opaque to application) init-options type, create/destroy +functions for it, set-creds/set-keytab/set-password functions, and a +kadm5-init-with-options function. (Optional: Reimplement the current +init functions as wrappers around these.) + +Add a set-context function which saves away in the init-options object +a krb5_context to be used in the new server handle instead of creating +a new one. (Destroying a server handle with such a "borrowed" krb5 +context should probably not destroy the context.) Calls within the +library should store any error messages in the context contained in +the server handle. Error messages produced during initialization +should also be stored in this context. + +The caller of these functions can use krb5_get_error_message to +extract the text of the error message from the supplied context. + +Unless we determine it's safe, we should probably assert (for now) +that each server handle must have a different context. (That's aside +from the thread safety issues.) + +These contexts should have been created with kadm5_init_krb5_context, +which will decide whether to look at the KDC config file depending on +whether you're using the client-side or server-side version of the +library. (Same as for kadmin vs kadmin.local.) + +Notes: + + * The existing API must continue to work, without changes. There is + external code we need to continue to support. + + * We considered a variant where the application could retrieve the + error message from the server handle using a new + kadm5_get_error_message function. However, the initialization code + is one likely place where the errors would occur (can't + authenticate, etc), and in that case, there is no server handle + from which to extract the context. + + A function to retrieve the library-created krb5_context from the + server handle would have the same problem. + + Using a separate approach to deal with errors at initialization + time, in combination with the above, might work. But we still wind + up either creating the init-with-options interface or adding + error-message-return variants of multiple existing init functions. + +To do: + + * Write up specifics (including function names -- the names used here + aren't meant to be definitive) and discuss on krbdev. + + * Implement library part. + + * Change kadmin and kdc to use it. diff --git a/krb5-1-7/doc/kadm5/adb-unit-test.tex b/krb5-1-7/doc/kadm5/adb-unit-test.tex new file mode 100644 index 000000000..d401342df --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5/api-funcspec.tex b/krb5-1-7/doc/kadm5/api-funcspec.tex new file mode 100644 index 000000000..bf885b464 --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5/api-server-design.tex b/krb5-1-7/doc/kadm5/api-server-design.tex new file mode 100644 index 000000000..61fc868fe --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5/api-unit-test.tex b/krb5-1-7/doc/kadm5/api-unit-test.tex new file mode 100644 index 000000000..3e0eb503e --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5/fullpage.sty b/krb5-1-7/doc/kadm5/fullpage.sty new file mode 100644 index 000000000..d5a2bf5b0 --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5/rcsid.sty b/krb5-1-7/doc/kadm5/rcsid.sty new file mode 100644 index 000000000..3ad7826ff --- /dev/null +++ b/krb5-1-7/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-7/doc/kadm5acl.texinfo b/krb5-1-7/doc/kadm5acl.texinfo new file mode 100644 index 000000000..468a9b93a --- /dev/null +++ b/krb5-1-7/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-7/doc/kadmin/README b/krb5-1-7/doc/kadmin/README new file mode 100644 index 000000000..72b369499 --- /dev/null +++ b/krb5-1-7/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-7/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt b/krb5-1-7/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt new file mode 100644 index 000000000..e235bec58 --- /dev/null +++ b/krb5-1-7/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-7/doc/kadmin/kadmin.protocol b/krb5-1-7/doc/kadmin/kadmin.protocol new file mode 100644 index 000000000..5e48945f6 --- /dev/null +++ b/krb5-1-7/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-7/doc/kadmin/kpasswd.protocol b/krb5-1-7/doc/kadmin/kpasswd.protocol new file mode 100644 index 000000000..7d77a2183 --- /dev/null +++ b/krb5-1-7/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-7/doc/kdcconf.texinfo b/krb5-1-7/doc/kdcconf.texinfo new file mode 100644 index 000000000..51583714e --- /dev/null +++ b/krb5-1-7/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-7/doc/kim/Doxyfile b/krb5-1-7/doc/kim/Doxyfile new file mode 100644 index 000000000..0f3151645 --- /dev/null +++ b/krb5-1-7/doc/kim/Doxyfile @@ -0,0 +1,282 @@ +# Doxyfile 1.5.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Kerberos Identity Management " +PROJECT_NUMBER = +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = YES +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text " +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../src/include/kim \ + ../../Sources/include/kim +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = NO +GENERATE_HTMLHELP = NO +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = letter +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = YES +RTF_OUTPUT = rtf +COMPACT_RTF = YES +RTF_HYPERLINKS = YES +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = NO +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = /Volumes/Ragna-Blade/Applications/Doxygen/Doxygen.app/Contents/Resources/ +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/krb5-1-7/doc/kim/html/doxygen.css b/krb5-1-7/doc/kim/html/doxygen.css new file mode 100644 index 000000000..c7db1a8a0 --- /dev/null +++ b/krb5-1-7/doc/kim/html/doxygen.css @@ -0,0 +1,358 @@ +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%; +} +H2 { + font-size: 120%; +} +H3 { + 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; +} + +/* 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%; } diff --git a/krb5-1-7/doc/kim/html/doxygen.png b/krb5-1-7/doc/kim/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/krb5-1-7/doc/kim/html/group__kim__ccache__iterator__reference.html b/krb5-1-7/doc/kim/html/group__kim__ccache__iterator__reference.html new file mode 100644 index 000000000..4b51443cd --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__ccache__iterator__reference.html @@ -0,0 +1,114 @@ + + +Kerberos Identity Management: KIM CCache Iterator Reference Documentation + + + + +

KIM CCache Iterator Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + +
kim_error kim_ccache_iterator_create (kim_ccache_iterator out_ccache_iterator  ) 
+
+
+ +

+Get a ccache iterator to enumerate ccaches in the cache collection. +

+

Parameters:
+ + +
out_ccache_iterator on exit, a ccache iterator object for the cache collection.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_iterator_next (kim_ccache_iterator  in_ccache_iterator,
kim_ccache out_ccache 
)
+
+
+ +

+Get the next ccache in the cache collection. +

+

Parameters:
+ + + +
in_ccache_iterator a ccache iterator object.
out_ccache on exit, the next ccache in the cache collection. If there are no more ccaches in the cache collection this argument will be set to NULL.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_ccache_iterator_free (kim_ccache_iterator io_ccache_iterator  ) 
+
+
+ +

+Free memory associated with a ccache iterator. +

+

Parameters:
+ + +
io_ccache_iterator a ccache iterator object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__ccache__reference.html b/krb5-1-7/doc/kim/html/group__kim__ccache__reference.html new file mode 100644 index 000000000..57886e601 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__ccache__reference.html @@ -0,0 +1,1217 @@ + + +Kerberos Identity Management: KIM CCache Reference Documentation + + + + +

KIM CCache Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_new (kim_ccache out_ccache,
kim_identity  in_client_identity,
kim_options  in_options 
)
+
+
+ +

+Acquire a new initial credential and store it in a ccache. +

+

Parameters:
+ + + + +
out_ccache on exit, a new cache object for a ccache containing a newly acquired initial credential. Must be freed with kim_ccache_free().
in_client_identity a client identity to obtain a credential for. Specify KIM_IDENTITY_ANY to allow the user to choose.
in_options options to control credential acquisition.
+
+
Note:
kim_ccache_create_new() may present a GUI or command line prompt to obtain information from the user.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_new_with_password (kim_ccache out_ccache,
kim_identity  in_client_identity,
kim_options  in_options,
kim_string  in_password 
)
+
+
+ +

+Acquire a new initial credential and store it in a ccache using the provided password.. +

+

Parameters:
+ + + + + +
out_ccache on exit, a new cache object for a ccache containing a newly acquired initial credential. Must be freed with kim_ccache_free().
in_client_identity a client identity to obtain a credential for. Specify KIM_IDENTITY_ANY to allow the user to choose.
in_options options to control credential acquisition.
in_password a password to be used while obtaining credentials.
+
+
Note:
kim_ccache_create_new_with_password() exists to support legacy password-based Kerberos environments. You should not use this function unless you know that it will only be used in environments using passwords. This function may also present a GUI or command line prompt to obtain additional information needed to obtain credentials (eg: SecurID pin).
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_new_if_needed (kim_ccache out_ccache,
kim_identity  in_client_identity,
kim_options  in_options 
)
+
+
+ +

+Find a ccache containing a valid initial credential in the cache collection, or if unavailable, acquire and store a new initial credential. +

+

Parameters:
+ + + + +
out_ccache on exit, a ccache object for a ccache containing a newly acquired initial credential. Must be freed with kim_ccache_free().
in_client_identity a client identity to obtain a credential for.
in_options options to control credential acquisition (if a credential is acquired).
+
+
Note:
kim_ccache_create_new_if_needed() may present a GUI or command line prompt to obtain information from the user.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_new_if_needed_with_password (kim_ccache out_ccache,
kim_identity  in_client_identity,
kim_options  in_options,
kim_string  in_password 
)
+
+
+ +

+Find a ccache containing a valid initial credential in the cache collection, or if unavailable, acquire and store a new initial credential using the provided password. +

+

Parameters:
+ + + + + +
out_ccache on exit, a ccache object for a ccache containing a newly acquired initial credential. Must be freed with kim_ccache_free().
in_client_identity a client identity to obtain a credential for.
in_options options to control credential acquisition (if a credential is acquired).
in_password a password to be used while obtaining credentials.
+
+
Note:
kim_ccache_create_new_if_needed_with_password() exists to support legacy password-based Kerberos environments. You should not use this function unless you know that it will only be used in environments using passwords. This function may also present a GUI or command line prompt to obtain additional information needed to obtain credentials (eg: SecurID pin).
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_from_client_identity (kim_ccache out_ccache,
kim_identity  in_client_identity 
)
+
+
+ +

+Find a ccache for a client identity in the cache collection. +

+

Parameters:
+ + + +
out_ccache on exit, a ccache object for a ccache containing a TGT credential. Must be freed with kim_ccache_free().
in_client_identity a client identity to find a ccache for. If in_client_identity is KIM_IDENTITY_ANY, this function returns the default ccache (ie: is equivalent to kim_ccache_create_from_default()).
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_from_keytab (kim_ccache out_ccache,
kim_identity  in_identity,
kim_options  in_options,
kim_string  in_keytab 
)
+
+
+ +

+Acquire a new initial credential from a keytab and store it in a ccache. +

+

Parameters:
+ + + + + +
out_ccache on exit, a new ccache object containing an initial credential for the client identity in_identity obtained using in_keytab. Must be freed with kim_ccache_free().
in_identity a client identity to obtain a credential for. Specify NULL for the first client identity in the keytab.
in_options options to control credential acquisition.
in_keytab a path to a keytab. Specify NULL for the default keytab location.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_ccache_create_from_default (kim_ccache out_ccache  ) 
+
+
+ +

+Get the default ccache. +

+

Parameters:
+ + +
out_ccache on exit, a ccache object for the default ccache. Must be freed with kim_ccache_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_from_display_name (kim_ccache out_ccache,
kim_string  in_display_name 
)
+
+
+ +

+Get a ccache for a ccache display name. +

+

Parameters:
+ + + +
out_ccache on exit, a ccache object for the ccache identified by in_display_name. Must be freed with kim_ccache_free().
in_display_name a ccache display name string (ie: "TYPE:NAME").
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This API is used to obtain a kim_ccache for a ccache name entered by the user.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_from_type_and_name (kim_ccache out_ccache,
kim_string  in_type,
kim_string  in_name 
)
+
+
+ +

+Get a ccache for a ccache type and name. +

+

Parameters:
+ + + + +
out_ccache on exit, a ccache object for the ccache identified by in_type and in_name. Must be freed with kim_ccache_free().
in_type a ccache type string.
in_name a ccache name string.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This API is provided for backwards compatibilty with applications which are not KIM-aware and should be avoided whenever possible.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_create_from_krb5_ccache (kim_ccache out_ccache,
krb5_context  in_krb5_context,
krb5_ccache  in_krb5_ccache 
)
+
+
+ +

+Get a ccache for a krb5 ccache. +

+

Parameters:
+ + + + +
out_ccache on exit, a new ccache object which is a copy of in_krb5_ccache. Must be freed with kim_ccache_free().
in_krb5_context the krb5 context used to create in_krb5_ccache.
in_krb5_ccache a krb5 ccache object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_copy (kim_ccache out_ccache,
kim_ccache  in_ccache 
)
+
+
+ +

+Copy a ccache. +

+

Parameters:
+ + + +
out_ccache on exit, the new ccache object which is a copy of in_ccache. Must be freed with kim_ccache_free().
in_ccache a ccache object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_compare (kim_ccache  in_ccache,
kim_ccache  in_compare_to_ccache,
kim_comparison out_comparison 
)
+
+
+ +

+Compare ccache objects. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_compare_to_ccache a ccache object.
out_comparison on exit, a comparison of in_ccache and in_compare_to_ccache which determines whether or not the two ccache objects refer to the same ccache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_krb5_ccache (kim_ccache  in_ccache,
krb5_context  in_krb5_context,
krb5_ccache *  out_krb5_ccache 
)
+
+
+ +

+Get a krb5 ccache for a ccache. +

+

Parameters:
+ + + + +
in_ccache a ccache object.
in_krb5_context a krb5 context which will be used to create out_krb5_ccache.
out_krb5_ccache on exit, a new krb5 ccache object which is a copy of in_ccache. Must be freed with krb5_cc_close() or krb5_cc_destroy().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_name (kim_ccache  in_ccache,
kim_string out_name 
)
+
+
+ +

+Get the name of a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_name on exit, the name string of in_ccache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_type (kim_ccache  in_ccache,
kim_string out_type 
)
+
+
+ +

+Get the type of a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_type on exit, the type string of in_ccache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_display_name (kim_ccache  in_ccache,
kim_string out_display_name 
)
+
+
+ +

+Get the type and name for a ccache in display format. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_display_name on exit, the type and name of in_ccache in a format appropriate for display to the user in command line programs. (ie: "<type>:<name>") Must be freed with kim_string_free(). Note: this string can also be passed to krb5_cc_resolve().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_client_identity (kim_ccache  in_ccache,
kim_identity out_client_identity 
)
+
+
+ +

+Get the client identity for a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_client_identity on exit, an identity object containing the client identity of in_ccache. Must be freed with kim_identity_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_valid_credential (kim_ccache  in_ccache,
kim_credential out_credential 
)
+
+
+ +

+Get the first valid credential in a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_credential on exit, the first valid credential in in_ccache. Must be freed with kim_credential_free(). Set to NULL if you only want return value, not the actual credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This function prefers valid TGT credentials. If there are only non-valid TGTs in the ccache, it will always return an error. However, if there are no TGTs at all, it will return the first valid non-TGT credential. If you only want TGTs, use kim_credential_is_tgt() to verify that out_credential is a tgt.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_state (kim_ccache  in_ccache,
kim_credential_state out_state 
)
+
+
+ +

+Check the state of the credentials in a ccache (valid, expired, postdated, etc). +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_state on exit, the state of the credentials in in_ccache. See kim_credential_state_enum for the possible values of out_state.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This function prefers TGT credentials. If there are any TGTs in the ccache, it will always return their state. However, if there are no TGTs at all, it will return the state of the first non-TGT credential.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_start_time (kim_ccache  in_ccache,
kim_time out_start_time 
)
+
+
+ +

+Get the time when the credentials in the ccache become valid. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_start_time on exit, the time when the credentials in in_ccache become valid. May be in the past or future.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_expiration_time (kim_ccache  in_ccache,
kim_time out_expiration_time 
)
+
+
+ +

+Get the time when the credentials in the ccache will expire. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_expiration_time on exit, the time when the credentials in in_ccache will expire. May be in the past or future.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_renewal_expiration_time (kim_ccache  in_ccache,
kim_time out_renewal_expiration_time 
)
+
+
+ +

+Get the time when the credentials in the ccache will no longer be renewable. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_renewal_expiration_time on exit, the time when the credentials in in_ccache will no longer be renewable. May be in the past or future.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_get_options (kim_ccache  in_ccache,
kim_options out_options 
)
+
+
+ +

+Get a kim_options object based on a ccache's credential attributes. +

+

Parameters:
+ + + +
in_ccache a ccache object.
out_options on exit, an options object reflecting the ticket options of the credentials in in_ccache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_ccache_set_default (kim_ccache  io_ccache  ) 
+
+
+ +

+Set a ccache to the default ccache. +

+

Parameters:
+ + +
io_ccache a ccache object which will be set to the default ccache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This API is provided for backwards compatibilty with applications which are not KIM-aware and should be avoided whenever possible.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_verify (kim_ccache  in_ccache,
kim_identity  in_service_identity,
kim_string  in_keytab,
kim_boolean  in_fail_if_no_service_key 
)
+
+
+ +

+Verify the TGT in a ccache. +

+

Parameters:
+ + + + + +
in_ccache a ccache object containing the TGT credential to be verified.
in_service_identity a service identity to look for in the keytab. Specify KIM_IDENTITY_ANY to use the default service identity (usually host/<host's FQDN><host's local realm>).
in_keytab a path to a keytab. Specify NULL for the default keytab location.
in_fail_if_no_service_key whether or not the absence of a key for in_service_identity in the host's keytab will cause a failure.
+
+
Note:
specifying FALSE for in_fail_if_no_service_key may expose the calling program to the Zanarotti attack if the host has no keytab installed.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_renew (kim_ccache  in_ccache,
kim_options  in_options 
)
+
+
+ +

+Renew the TGT in a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object containing a TGT to be renewed.
in_options initial credential options to be used if a new credential is obtained.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_ccache_validate (kim_ccache  in_ccache,
kim_options  in_options 
)
+
+
+ +

+Validate the TGT in a ccache. +

+

Parameters:
+ + + +
in_ccache a ccache object containing a TGT to be validated.
in_options initial credential options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_ccache_destroy (kim_ccache io_ccache  ) 
+
+
+ +

+Remove a ccache from the cache collection. +

+

Parameters:
+ + +
io_ccache a ccache object to be destroyed. Set to NULL on exit.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
Frees memory associated with the ccache. Do not call kim_ccache_free() after calling this function.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_ccache_free (kim_ccache io_ccache  ) 
+
+
+ +

+Free memory associated with a ccache. +

+

Parameters:
+ + +
io_ccache a ccache object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__credential__iterator__reference.html b/krb5-1-7/doc/kim/html/group__kim__credential__iterator__reference.html new file mode 100644 index 000000000..770119554 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__credential__iterator__reference.html @@ -0,0 +1,124 @@ + + +Kerberos Identity Management: KIM Credential Iterator Reference Documentation + + + + +

KIM Credential Iterator Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_iterator_create (kim_credential_iterator out_credential_iterator,
kim_ccache  in_ccache 
)
+
+
+ +

+Get a credential iterator to enumerate credentials in a ccache. +

+

Parameters:
+ + + +
out_credential_iterator on exit, a credential iterator object for in_ccache. Must be freed with kim_credential_iterator_free().
in_ccache a ccache object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_iterator_next (kim_credential_iterator  in_credential_iterator,
kim_credential out_credential 
)
+
+
+ +

+Get the next credential in a ccache. +

+

Parameters:
+ + + +
in_credential_iterator a credential iterator object.
out_credential on exit, the next credential in the ccache iterated by in_credential_iterator. Must be freed with kim_credential_free(). If there are no more credentials this argument will be set to NULL.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_credential_iterator_free (kim_credential_iterator io_credential_iterator  ) 
+
+
+ +

+Free memory associated with a credential iterator. +

+

Parameters:
+ + +
io_credential_iterator a credential iterator object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__credential__reference.html b/krb5-1-7/doc/kim/html/group__kim__credential__reference.html new file mode 100644 index 000000000..2cd1f787c --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__credential__reference.html @@ -0,0 +1,830 @@ + + +Kerberos Identity Management: KIM Credential Reference Documentation + + + + +

KIM Credential Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_create_new (kim_credential out_credential,
kim_identity  in_client_identity,
kim_options  in_options 
)
+
+
+ +

+Acquire a new initial credential. +

+

Parameters:
+ + + + +
out_credential on exit, a new credential object containing a newly acquired initial credential. Must be freed with kim_credential_free().
in_client_identity a client identity to obtain a credential for. Specify NULL to allow the user to choose the identity
in_options options to control credential acquisition.
+
+
Note:
kim_credential_create_new() may present a GUI or command line prompt to obtain information from the user.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_create_new
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_create_new_with_password (kim_credential out_credential,
kim_identity  in_client_identity,
kim_options  in_options,
kim_string  in_password 
)
+
+
+ +

+Acquire a new initial credential using the provided password. +

+

Parameters:
+ + + + + +
out_credential on exit, a new credential object containing a newly acquired initial credential. Must be freed with kim_credential_free().
in_client_identity a client identity to obtain a credential for. Specify NULL to allow the user to choose the identity
in_options options to control credential acquisition.
in_password a password to be used while obtaining the credential.
+
+
Note:
kim_credential_create_new_with_password() exists to support legacy password-based Kerberos environments. You should not use this function unless you know that it will only be used in environments using passwords. This function may also present a GUI or command line prompt to obtain additional information needed to obtain credentials (eg: SecurID pin).
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_create_new
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_create_from_keytab (kim_credential out_credential,
kim_identity  in_identity,
kim_options  in_options,
kim_string  in_keytab 
)
+
+
+ +

+Acquire a new initial credential from a keytab. +

+

Parameters:
+ + + + + +
out_credential on exit, a new credential object containing an initial credential for in_identity obtained using in_keytab. Must be freed with kim_credential_free().
in_identity a client identity to obtain a credential for. Specify NULL for the first identity in the keytab.
in_options options to control credential acquisition.
in_keytab a path to a keytab. Specify NULL for the default keytab location.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_create_from_keytab
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_create_from_krb5_creds (kim_credential out_credential,
krb5_context  in_krb5_context,
krb5_creds *  in_krb5_creds 
)
+
+
+ +

+Copy a credential from a krb5 credential object. +

+

Parameters:
+ + + + +
out_credential on exit, a new credential object which is a copy of in_krb5_creds. Must be freed with kim_credential_free().
in_krb5_context the krb5 context used to create in_krb5_creds.
in_krb5_creds a krb5 credential object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_copy (kim_credential out_credential,
kim_credential  in_credential 
)
+
+
+ +

+Copy a credential object. +

+

Parameters:
+ + + +
out_credential on exit, a new credential object which is a copy of in_credential. Must be freed with kim_credential_free().
in_credential a credential object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_krb5_creds (kim_credential  in_credential,
krb5_context  in_krb5_context,
krb5_creds **  out_krb5_creds 
)
+
+
+ +

+Get a krb5 credentials object for a credential object. +

+

Parameters:
+ + + + +
in_credential a credential object.
in_krb5_context a krb5 context which will be used to create out_krb5_creds.
out_krb5_creds on exit, a new krb5 creds object which is a copy of in_credential. Must be freed with krb5_free_creds().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_client_identity (kim_credential  in_credential,
kim_identity out_client_identity 
)
+
+
+ +

+Get the client identity of a credential object. +

+

Parameters:
+ + + +
in_credential a credential object.
out_client_identity on exit, an identity object containing the client identity of in_credential. Must be freed with kim_identity_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_service_identity (kim_credential  in_credential,
kim_identity out_service_identity 
)
+
+
+ +

+Get the service identity of a credential object. +

+

Parameters:
+ + + +
in_credential a credential object.
out_service_identity on exit, an identity object containing the service identity of in_credential. Must be freed with kim_identity_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_is_tgt (kim_credential  in_credential,
kim_boolean out_is_tgt 
)
+
+
+ +

+Check if a credential is a ticket granting ticket. +

+

Parameters:
+ + + +
in_credential a credential object.
out_is_tgt on exit, whether or not the credential is a TGT.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_state (kim_credential  in_credential,
kim_credential_state out_state 
)
+
+
+ +

+Check the state of a credential (valid, expired, postdated, etc). +

+

Parameters:
+ + + +
in_credential a credential object.
out_state on exit, the state of the credential. See kim_credential_state_enum for the possible values of out_state.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_start_time (kim_credential  in_credential,
kim_time out_start_time 
)
+
+
+ +

+Get the time when the credentials become valid. +

+

Parameters:
+ + + +
in_credential a credential object.
out_start_time on exit, the time when in_credential becomes valid. May be in the past or future.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_get_start_time
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_expiration_time (kim_credential  in_credential,
kim_time out_expiration_time 
)
+
+
+ +

+Get the time when the credentials will expire. +

+

Parameters:
+ + + +
in_credential a credential object.
out_expiration_time on exit, the time when in_credential will expire. May be in the past or future.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_get_expiration_time
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_renewal_expiration_time (kim_credential  in_credential,
kim_time out_renewal_expiration_time 
)
+
+
+ +

+Get the time when the credentials will no longer be renewable. +

+

Parameters:
+ + + +
in_credential a credential object.
out_renewal_expiration_time on exit, the time when in_credential will no longer be renewable. May be in the past or future. If credentials are not renewable at all, returns 0.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_get_renewal_expiration_time
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_get_options (kim_credential  in_credential,
kim_options out_options 
)
+
+
+ +

+Get a kim_options object based on a credential's attributes. +

+

Parameters:
+ + + +
in_credential a credential object.
out_options on exit, an options object reflecting the ticket options of in_credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_store (kim_credential  in_credential,
kim_identity  in_client_identity,
kim_ccache out_ccache 
)
+
+
+ +

+Store a credential in a ccache in the cache collection. +

+

Parameters:
+ + + + +
in_credential a credential object.
in_client_identity a client identity.
out_ccache on exit, a ccache object containing in_credential with the client identity in_client_identity. Must be freed with kim_ccache_free(). Specify NULL if you don't want this return value.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_credential_verify (kim_credential  in_credential,
kim_identity  in_service_identity,
kim_string  in_keytab,
kim_boolean  in_fail_if_no_service_key 
)
+
+
+ +

+Verify a TGT credential. +

+

Parameters:
+ + + + + +
in_credential a TGT credential to be verified.
in_service_identity a service identity to look for in the keytab. Specify KIM_IDENTITY_ANY to use the default service identity (usually host/<host's FQDN><host's local realm>).
in_keytab a path to a keytab. Specify NULL for the default keytab location.
in_fail_if_no_service_key whether or not the absence of a key for in_service_identity in the host's keytab will cause a failure.
+
+
Note:
specifying FALSE for in_fail_if_no_service_key may expose the calling program to the Zanarotti attack if the host has no keytab installed.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_verify
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_renew (kim_credential io_credential,
kim_options  in_options 
)
+
+
+ +

+Renew a TGT credential. +

+

Parameters:
+ + + +
io_credential a TGT credential to be renewed. On exit, the old credential object will be freed and io_credential will be replaced with a new renewed credential. The new credential must be freed with kim_credential_free().
in_options initial credential options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_renew
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_credential_validate (kim_credential io_credential,
kim_options  in_options 
)
+
+
+ +

+Validate a TGT credential. +

+

Parameters:
+ + + +
io_credential a credential object to be validated. On exit, the old credential object will be freed and io_credential will be replaced with a new validated credential. The new credential must be freed with kim_credential_free().
in_options initial credential options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_ccache_validate
+ +
+

+ +

+
+ + + + + + + + + +
void kim_credential_free (kim_credential io_credential  ) 
+
+
+ +

+Free memory associated with a credential object. +

+

Parameters:
+ + +
io_credential the credential object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__error__reference.html b/krb5-1-7/doc/kim/html/group__kim__error__reference.html new file mode 100644 index 000000000..8cba97787 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__error__reference.html @@ -0,0 +1,58 @@ + + +Kerberos Identity Management: KIM Error Reference Documentation + + + + +

KIM Error Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_string_get_last_error_message (kim_string out_string,
kim_error  in_error 
)
+
+
+ +

+Get a text description of an error suitable for display to the user. +

+

Parameters:
+ + + +
out_string On success, a human-readable UTF-8 string describing the error representedby in_error. Must be freed with kim_string_free().
in_error an error code. Used to verify that the correct error string will be returned (see note below).
+
+
Returns:
On success, KIM_NO_ERROR.
+
Note:
This API is implemented using thread local storage. It should be called immediately after a KIM API returns an error code so that the correct string is returned. The returned copy may then be held by the caller until needed. If in_error does not match the last saved error KIM may return a less descriptive string.
+ +
+

+


Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__favorite__identities__reference.html b/krb5-1-7/doc/kim/html/group__kim__favorite__identities__reference.html new file mode 100644 index 000000000..cf80ba42d --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__favorite__identities__reference.html @@ -0,0 +1,306 @@ + + +Kerberos Identity Management: KIM Favorite Identities Documentation + + + + +

KIM Favorite Identities Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + +
kim_error_t kim_favorite_identities_create (kim_favorite_identities_t out_favorite_identities  ) 
+
+
+ +

+Create a new favorite identities list. +

+

Parameters:
+ + +
out_favorite_identities on exit, a new favorite identities object. Must be freed with kim_favorite_identities_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error_t kim_favorite_identities_copy (kim_favorite_identities_t out_favorite_identities,
kim_favorite_identities_t  in_favorite_identities 
)
+
+
+ +

+Copy a favorite identities list. +

+

Parameters:
+ + + +
out_favorite_identities on exit, a new favorite identities object which is a copy of in_favorite_identities. Must be freed with kim_favorite_identities_free().
in_favorite_identities a favorite identities object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error_t kim_favorite_identities_get_number_of_identities (kim_favorite_identities_t  in_favorite_identities,
kim_count_t out_number_of_identities 
)
+
+
+ +

+Get the number of identities in a favorite identities list. +

+

Parameters:
+ + + +
in_favorite_identities a favorite identities object.
out_number_of_identities on exit, the number of identities in in_favorite_identities.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error_t kim_favorite_identities_get_identity_at_index (kim_favorite_identities_t  in_favorite_identities,
kim_count_t  in_index,
kim_identity_t out_identity 
)
+
+
+ +

+Get the Nth identity in a favorite identities list. +

+

Parameters:
+ + + + +
in_favorite_identities a favorite identities object.
in_index a index into the identities list (starting at 0).
out_realm on exit, the identity at in_index in in_favorite_identities. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error_t kim_favorite_identities_add_identity (kim_favorite_identities_t  io_favorite_identities,
kim_identity_t  in_identity 
)
+
+
+ +

+Add an identity to a favorite identities list. +

+

Parameters:
+ + + +
io_favorite_identities a favorite identities object.
in_identity an identity string to add to in_favorite_identities.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error_t kim_favorite_identities_remove_identity (kim_favorite_identities_t  io_favorite_identities,
kim_identity_t  in_identity 
)
+
+
+ +

+Remove an identity from a identities list. +

+

Parameters:
+ + + +
io_favorite_identities a favorite identities object.
in_identity an identity to remove from in_favorite_identities.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error_t kim_favorite_identities_remove_all_identities (kim_favorite_identities_t  io_favorite_identities  ) 
+
+
+ +

+Empty a favorite identities list. +

+

Parameters:
+ + +
io_favorite_identities a favorite identities object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error object representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_favorite_identities_free (kim_favorite_identities_t io_favorite_identities  ) 
+
+
+ +

+Free memory associated with an identities list. +

+

Parameters:
+ + +
io_favorite_identities the favorite identities object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Wed May 7 15:22:20 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__identity__reference.html b/krb5-1-7/doc/kim/html/group__kim__identity__reference.html new file mode 100644 index 000000000..c975c731c --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__identity__reference.html @@ -0,0 +1,589 @@ + + +Kerberos Identity Management: KIM Identity Reference Documentation + + + + +

KIM Identity Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_create_from_string (kim_identity out_identity,
kim_string  in_string 
)
+
+
+ +

+Create a identity from a string. +

+

Parameters:
+ + + +
out_identity on exit, a new identity object. Must be freed with kim_identity_free().
in_string a string representation of a Kerberos identity. Special characters such as '/' and '@' must be escaped with '\'.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_identity_create_from_components (kim_identity out_identity,
kim_string  in_realm,
kim_string  in_1st_component,
  ... 
)
+
+
+ +

+Create a identity from a realm and component strings. +

+

Parameters:
+ + + + + +
out_identity on exit, a new identity object. Must be freed with kim_identity_free().
in_realm a string representation of a Kerberos realm.
in_1st_component a string representing the first component of the identity.
... zero or more strings of type kim_string_t representing additional components of the identity followed by a terminating NULL. Components will be assembled in order (ie: the 4th argument to kim_identity_create_from_components() will be the 2nd component of the identity).
+
+
Note:
The last argument must be a NULL or kim_identity_create_from_components() may crash.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_identity_create_from_krb5_principal (kim_identity out_identity,
krb5_context  in_krb5_context,
krb5_principal  in_krb5_principal 
)
+
+
+ +

+Create an identity object from a krb5_principal. +

+

Parameters:
+ + + + +
out_identity on exit, a new identity object which is a copy of in_krb5_principal. Must be freed with kim_identity_free().
in_krb5_context the krb5 context used to create in_krb5_principal.
in_krb5_principal a krb5 principal object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_copy (kim_identity out_identity,
kim_identity  in_identity 
)
+
+
+ +

+Copy an identity object. +

+

Parameters:
+ + + +
out_identity on exit, a new identity object which is a copy of in_identity. Must be freed with kim_identity_free().
in_identity an identity object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_identity_compare (kim_identity  in_identity,
kim_identity  in_compare_to_identity,
kim_comparison out_comparison 
)
+
+
+ +

+Compare identity objects for equivalency. +

+

Parameters:
+ + + + +
in_identity an identity object.
in_compare_to_identity an identity object.
out_comparison on exit, a comparison of in_identity and in_compare_to_identity which determines whether or not the two identities are equivalent and their sort order (for display to the user) if they are not.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_string (kim_identity  in_identity,
kim_string out_string 
)
+
+
+ +

+Get the string representation of a identity. +

+

Parameters:
+ + + +
in_identity an identity object.
out_string on exit, a string representation of in_identity. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
Special characters such as '@' and '/' will be escaped with '\'.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_display_string (kim_identity  in_identity,
kim_string out_display_string 
)
+
+
+ +

+Get a human-readable string representation of an identity. +

+

Parameters:
+ + + +
in_identity an identity object.
out_display_string on exit, a string representation of in_identity appropriate for display to the user. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
Special characters such as '/' and '@' are not escaped with '\'. As a result the string returned from this function cannot be used with kim_identity_create_from_string() because it does not uniquely specify a principal. The result of this function should only be used to display to the user.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_realm (kim_identity  in_identity,
kim_string out_realm_string 
)
+
+
+ +

+Get the realm string of an identity. +

+

Parameters:
+ + + +
in_identity an identity object.
out_realm_string on exit, a string representation of in_identity's realm. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_number_of_components (kim_identity  in_identity,
kim_count out_number_of_components 
)
+
+
+ +

+Get the number of components of an identity. +

+

Parameters:
+ + + +
in_identity an identity object.
out_number_of_components on exit the number of components in in_identity.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_component_at_index (kim_identity  in_identity,
kim_count  in_index,
kim_string out_component_string 
)
+
+
+ +

+Get the Nth component of an identity. +

+

Parameters:
+ + + + +
in_identity an identity object.
in_index the index of the desired component. Component indexes start at 0.
out_component_string on exit, a string representation of the component in in_identity specified by in_index. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_components_string (kim_identity  in_identity,
kim_string out_components 
)
+
+
+ +

+Get a display string of the non-realm components of an identity. +

+

Parameters:
+ + + +
in_identity an identity object.
out_components on exit, a string of the non-realm components of in_identity separated by '/' characters. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_identity_get_krb5_principal (kim_identity  in_identity,
krb5_context  in_krb5_context,
krb5_principal *  out_krb5_principal 
)
+
+
+ +

+Get the krb5_principal representation of an identity. +

+

Parameters:
+ + + + +
in_identity an identity object.
in_krb5_context a krb5 context object.
out_krb5_principal on exit, a krb5_principal representation of in_identity allocated with in_krb5_context. Must be freed with krb5_free_principal() using in_krb5_context.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_identity_change_password (kim_identity  in_identity  ) 
+
+
+ +

+Change the password for an identity. +

+

Parameters:
+ + +
in_identity an identity object whose password will be changed.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
kim_identity_change_password() will acquire a temporary credential to change the password.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_identity_free (kim_identity io_identity  ) 
+
+
+ +

+Free memory associated with an identity. +

+

Parameters:
+ + +
io_identity the identity object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__library__reference.html b/krb5-1-7/doc/kim/html/group__kim__library__reference.html new file mode 100644 index 000000000..c646557b7 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__library__reference.html @@ -0,0 +1,225 @@ + + +Kerberos Identity Management: KIM Library Documentation + + + + +

KIM Library Documentation

+

+

Defines

+ +

Typedefs

+ +

Functions

+ +

Define Documentation

+ +
+
+ + + + +
#define KIM_UI_ENVIRONMENT_NONE   0
+
+
+ +

+Do not present user interface +

+

+ +

+
+ + + + +
#define KIM_UI_ENVIRONMENT_AUTO   1
+
+
+ +

+Automatically determine what user interface is appropriate (default). +

+

+ +

+
+ + + + +
#define KIM_UI_ENVIRONMENT_GUI   2
+
+
+ +

+Present a graphical user interface +

+

+ +

+
+ + + + +
#define KIM_UI_ENVIRONMENT_CLI   3
+
+
+ +

+Present a command line user interface +

+

+


Typedef Documentation

+ +
+
+ + + + +
typedef int kim_ui_environment
+
+
+ +

+An integer describing the type of user interface to use. +

+

+


Function Documentation

+ +
+
+ + + + + + + + + +
kim_error kim_library_set_ui_environment (kim_ui_environment  in_ui_environment  ) 
+
+
+ +

+Tell KIM how to present UI from your application. +

+

Parameters:
+ + +
in_ui_environment an integer value describing the type of user interface to use.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
Set to KIM_UI_ENVIRONMENT_AUTO by default.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_library_set_allow_home_directory_access (kim_boolean  in_allow_access  ) 
+
+
+ +

+Tells KIM whether or not it is allowed to touch the user's home directory. +

+

Parameters:
+ + +
in_allow_access a boolean containing whether or not to touch the user's home directory.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This API is usually used for Kerberos authenticated home directories to prevent a deadlock.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_library_set_allow_automatic_prompting (kim_boolean  in_allow_automatic_prompting  ) 
+
+
+ +

+Tells KIM whether or not it is allowed to automatically present user interface. +

+

Parameters:
+ + +
in_allow_automatic_prompting a boolean containing whether or not to prompt automatically.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_library_set_application_name (kim_string  in_application_name  ) 
+
+
+ +

+Set the name of your application for KIM to use for user interface. +

+

Parameters:
+ + +
in_application_name a string containing the localized name of your application.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
On many operating systems KIM can determine the caller's application name automatically. This call exists for applications to use when those mechanisms fail or do not exist.
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__options__reference.html b/krb5-1-7/doc/kim/html/group__kim__options__reference.html new file mode 100644 index 000000000..aea7292d7 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__options__reference.html @@ -0,0 +1,776 @@ + + +Kerberos Identity Management: KIM Options Reference Documentation + + + + +

KIM Options Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + +
kim_error kim_options_create (kim_options out_options  ) 
+
+
+ +

+Create new options with default values. +

+

Parameters:
+ + +
out_options on exit, a new options object. Must be freed with kim_options_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_copy (kim_options out_options,
kim_options  in_options 
)
+
+
+ +

+Copy options. +

+

Parameters:
+ + + +
out_options on exit, a new options object which is a copy of in_options. Must be freed with kim_options_free(). If passed KIM_OPTIONS_DEFAULT will set out_options to KIM_OPTIONS_DEFAULT.
in_options a options object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_start_time (kim_options  io_options,
kim_time  in_start_time 
)
+
+
+ +

+Set the date when a credential should become valid. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_start_time a start date (in seconds since January 1, 1970). Set to KIM_OPTIONS_START_IMMEDIATELY for the acquired credential to be valid immediately.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
When using a start time in the future, once the start time has been reached the credential must be validated before it can be used.
+
Default value
0, indicating "now". The credential will be valid immediately.
+
See also:
kim_options_get_start_time(), kim_credential_validate(), kim_ccache_validate(), kim_identity_validate()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_start_time (kim_options  in_options,
kim_time out_start_time 
)
+
+
+ +

+Get the date when a credential should become valid. +

+

Parameters:
+ + + +
in_options an options object.
out_start_time on exit, the start date (in seconds since January 1, 1970) specified by in_options. KIM_OPTIONS_START_IMMEDIATELY indicates the credential will be valid immediately.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
When using a start time in the future, once the start time has been reached the credential must be validated before it can be used.
+
Default value
0, indicating "now". The credential will be valid immediately.
+
See also:
kim_options_set_start_time(), kim_credential_validate(), kim_ccache_validate(), kim_identity_validate()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_lifetime (kim_options  io_options,
kim_lifetime  in_lifetime 
)
+
+
+ +

+Set the duration during which a credential should be valid. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_lifetime a lifetime duration (in seconds).
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). As a result the credential will actually have a lifetime which is the minimum of in_lifetime and the KDC's maximum allowed lifetime.
+
See also:
kim_options_get_lifetime()
+
Default value
Read from the user's preferences and the Kerberos configuration. 10 hours if unspecified.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_lifetime (kim_options  in_options,
kim_lifetime out_lifetime 
)
+
+
+ +

+Get the duration during which an acquired credential should be valid. +

+

Parameters:
+ + + +
in_options an options object.
out_lifetime on exit, the lifetime duration (in seconds) specified in in_options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). As a result the credential will actually have a lifetime which is the minimum of in_lifetime and the KDC's maximum allowed lifetime.
+
Default value
Read from the user's preferences and the Kerberos configuration. 10 hours if unspecified.
+
See also:
kim_options_set_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_renewable (kim_options  io_options,
kim_boolean  in_renewable 
)
+
+
+ +

+Set whether or not to request a renewable credential. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_renewable a boolean value indicating whether or not to request a renewable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_get_renewable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_renewable (kim_options  in_options,
kim_boolean out_renewable 
)
+
+
+ +

+Get whether or not to request a renewable credential. +

+

Parameters:
+ + + +
in_options an options object.
out_renewable on exit, a boolean value indicating whether or in_options will request a renewable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_set_renewable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_renewal_lifetime (kim_options  io_options,
kim_lifetime  in_renewal_lifetime 
)
+
+
+ +

+Set the duration during which a valid credential should be renewable. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_renewal_lifetime a renewal lifetime duration (in seconds).
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
KDCs have a maximum allowed renewal lifetime per identity (usually 10 to 21 hours). As a result the credential will actually have a lifetime which is the minimum of in_lifetime and the KDC's maximum allowed lifetime.
+
Default value
Read from the user's preferences and the Kerberos configuration. 7 days if unspecified.
+
See also:
kim_options_get_renewal_lifetime(), kim_identity_renew(), kim_credential_renew(), kim_ccache_renew()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_renewal_lifetime (kim_options  in_options,
kim_lifetime out_renewal_lifetime 
)
+
+
+ +

+Get the duration during which a valid credential should be renewable. +

+

Parameters:
+ + + +
in_options an options object.
out_renewal_lifetime on exit, the renewal lifetime duration (in seconds) specified in in_options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). As a result the credential will actually have a lifetime which is the minimum of in_lifetime and the KDC's maximum allowed lifetime.
+
Default value
Read from the user's preferences and the Kerberos configuration. 7 days if unspecified.
+
See also:
kim_options_set_renewal_lifetime(), kim_identity_renew(), kim_credential_renew(), kim_ccache_renew()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_forwardable (kim_options  io_options,
kim_boolean  in_forwardable 
)
+
+
+ +

+Set whether or not to request a forwardable credential. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_forwardable a boolean value indicating whether or not to request a forwardable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_get_forwardable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_forwardable (kim_options  in_options,
kim_boolean out_forwardable 
)
+
+
+ +

+Get whether or not to request a forwardable credential. +

+

Parameters:
+ + + +
in_options an options object.
out_forwardable on exit, a boolean value indicating whether or in_options will request a forwardable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_set_forwardable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_proxiable (kim_options  io_options,
kim_boolean  in_proxiable 
)
+
+
+ +

+Set whether or not to request a proxiable credential. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_proxiable a boolean value indicating whether or not to request a proxiable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_get_proxiable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_proxiable (kim_options  in_options,
kim_boolean out_proxiable 
)
+
+
+ +

+Get whether or not to request a proxiable credential. +

+

Parameters:
+ + + +
in_options an options object.
out_proxiable on exit, a boolean value indicating whether or in_options will request a proxiable credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_set_proxiable()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_addressless (kim_options  io_options,
kim_boolean  in_addressless 
)
+
+
+ +

+Set whether or not to request an addressless credential. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_addressless a boolean value indicating whether or not to request an addressless credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_get_addressless()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_addressless (kim_options  in_options,
kim_boolean out_addressless 
)
+
+
+ +

+Get whether or not to request an addressless credential. +

+

Parameters:
+ + + +
in_options an options object.
out_addressless on exit, a boolean value indicating whether or in_options will request an addressless credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
Read from the user's preferences and the Kerberos configuration. TRUE if unspecified.
+
See also:
kim_options_set_addressless()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_set_service_name (kim_options  io_options,
kim_string  in_service_name 
)
+
+
+ +

+Set the service name to request a credential for. +

+

Parameters:
+ + + +
io_options an options object to modify.
in_service_name a service name.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
NULL, indicating "krbtgt@<REALM>", the ticket granting ticket (TGT) service.
+
See also:
kim_options_get_service_name()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_options_get_service_name (kim_options  in_options,
kim_string out_service_name 
)
+
+
+ +

+Get the service name to request a credential for. +

+

Parameters:
+ + + +
in_options an options object.
out_service_name on exit, the service name specified in in_options. Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Default value
NULL, indicating "krbtgt@<REALM>", the ticket granting ticket (TGT) service.
+
See also:
kim_options_set_service_name()
+ +
+

+ +

+
+ + + + + + + + + +
void kim_options_free (kim_options io_options  ) 
+
+
+ +

+Free memory associated with an options object. +

+

Parameters:
+ + +
io_options the options object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__preferences__reference.html b/krb5-1-7/doc/kim/html/group__kim__preferences__reference.html new file mode 100644 index 000000000..5320884dd --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__preferences__reference.html @@ -0,0 +1,989 @@ + + +Kerberos Identity Management: KIM Preferences Documentation + + + + +

KIM Preferences Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + +
kim_error kim_preferences_create (kim_preferences out_preferences  ) 
+
+
+ +

+Create a new preferences object from the current user's preferences. +

+

Parameters:
+ + +
out_preferences on exit, a new preferences object. Must be freed with kim_preferences_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_copy (kim_preferences out_preferences,
kim_preferences  in_preferences 
)
+
+
+ +

+Copy a preferences object. +

+

Parameters:
+ + + +
out_preferences on exit, a new preferences object which is a copy of in_preferences. Must be freed with kim_preferences_free().
in_preferences a preferences object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_options (kim_preferences  io_preferences,
kim_options  in_options 
)
+
+
+ +

+Set the user's preferred options. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_options an options object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_options (kim_preferences  in_preferences,
kim_options out_options 
)
+
+
+ +

+Get the user's preferred options. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_options on exit, the options specified in in_preferences. May be KIM_OPTIONS_DEFAULT. If not, must be freed with kim_options_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_remember_options (kim_preferences  io_preferences,
kim_boolean  in_remember_options 
)
+
+
+ +

+Set whether or not to remember the last options the user used to acquire a credential. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_remember_options a boolean value indicating whether or not to remember the last options used to acquire a credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_remember_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_remember_options (kim_preferences  in_preferences,
kim_boolean out_remember_options 
)
+
+
+ +

+Get whether or not to remember the last options the user used to acquire a credential. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_remember_options on exit, a boolean value indicating whether or in_preferences will remember the last options used to acquire a credential.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_remember_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_client_identity (kim_preferences  io_preferences,
kim_identity  in_client_identity 
)
+
+
+ +

+Set the user's preferred client identity. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_client_identity a client identity object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_client_identity()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_client_identity (kim_preferences  in_preferences,
kim_identity out_client_identity 
)
+
+
+ +

+Get the user's preferred client identity. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_client_identity on exit, the client identity specified in in_preferences. Must be freed with kim_identity_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_client_identity()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_remember_client_identity (kim_preferences  io_preferences,
kim_boolean  in_remember_client_identity 
)
+
+
+ +

+Set whether or not to remember the last client identity the user acquired a credential for. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_remember_client_identity a boolean value indicating whether or not to remember the last client identity for which a credential was acquired.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_remember_client_identity()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_remember_client_identity (kim_preferences  in_preferences,
kim_boolean out_remember_client_identity 
)
+
+
+ +

+Get whether or not to remember the last client identity the user acquired a credential for. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_remember_client_identity on exit, a boolean value indicating whether or in_preferences will remember the last client identity for which a credential was acquired.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_remember_client_identity()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_minimum_lifetime (kim_preferences  io_preferences,
kim_lifetime  in_minimum_lifetime 
)
+
+
+ +

+Set the minimum credential lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_minimum_lifetime a minimum lifetime indicating how small a lifetime the GUI tools should allow the user to specify for credentials.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_minimum_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_minimum_lifetime (kim_preferences  in_preferences,
kim_lifetime out_minimum_lifetime 
)
+
+
+ +

+Get the minimum credential lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_minimum_lifetime on exit, the minimum lifetime that GUI tools will allow the user to specify for credentials.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_minimum_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_maximum_lifetime (kim_preferences  io_preferences,
kim_lifetime  in_maximum_lifetime 
)
+
+
+ +

+Set the maximum credential lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_maximum_lifetime a maximum lifetime indicating how large a lifetime the GUI tools should allow the user to specify for credentials.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_maximum_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_maximum_lifetime (kim_preferences  in_preferences,
kim_lifetime out_maximum_lifetime 
)
+
+
+ +

+Get the maximum credential lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_maximum_lifetime on exit, the maximum lifetime that GUI tools will allow the user to specify for credentials.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_maximum_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_minimum_renewal_lifetime (kim_preferences  io_preferences,
kim_lifetime  in_minimum_renewal_lifetime 
)
+
+
+ +

+Set the minimum credential renewal lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_minimum_renewal_lifetime a minimum lifetime indicating how small a lifetime the GUI tools should allow the user to specify for credential renewal.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_minimum_renewal_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_minimum_renewal_lifetime (kim_preferences  in_preferences,
kim_lifetime out_minimum_renewal_lifetime 
)
+
+
+ +

+Get the minimum credential renewal lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_minimum_renewal_lifetime on exit, the minimum lifetime that GUI tools will allow the user to specify for credential renewal.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_minimum_renewal_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_set_maximum_renewal_lifetime (kim_preferences  io_preferences,
kim_lifetime  in_maximum_renewal_lifetime 
)
+
+
+ +

+Set the maximum credential renewal lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
io_preferences a preferences object to modify.
in_maximum_renewal_lifetime a maximum lifetime indicating how large a lifetime the GUI tools should allow the user to specify for credential renewal.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_get_minimum_renewal_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_maximum_renewal_lifetime (kim_preferences  in_preferences,
kim_lifetime out_maximum_renewal_lifetime 
)
+
+
+ +

+Get the maximum credential renewal lifetime for GUI credential lifetime controls. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_maximum_renewal_lifetime on exit, the maximum lifetime that GUI tools will allow the user to specify for credential renewal.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_preferences_set_minimum_renewal_lifetime()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_number_of_favorite_identities (kim_preferences  in_preferences,
kim_count out_number_of_identities 
)
+
+
+ +

+Get the number of favorite identities in a preferences object. +

+

Parameters:
+ + + +
in_preferences a preferences object.
out_number_of_identities on exit, the number of identities in in_preferences.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_get_favorite_identity_at_index (kim_preferences  in_preferences,
kim_count  in_index,
kim_identity out_identity,
kim_options out_options 
)
+
+
+ +

+Get the Nth favorite identity in a preferences object. +

+

Parameters:
+ + + + + +
in_preferences a preferences object.
in_index a index into the identities list (starting at 0).
out_identity on exit, the identity at in_index in in_preferences. Must be freed with kim_string_free().
out_options on exit, the options associated with identity at in_index in in_favorite_identities. May be KIM_OPTIONS_DEFAULT. Pass NULL if you do not want the options associated with the identity. Must be freed with kim_options_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_add_favorite_identity (kim_preferences  io_preferences,
kim_identity  in_identity,
kim_options  in_options 
)
+
+
+ +

+Add a favorite identity to a preferences object. +

+

Parameters:
+ + + + +
io_preferences a preferences object.
in_identity an identity to add to io_preferences.
in_options options which will be associated with that identity. Use KIM_OPTIONS_DEFAULT if the identity should use the user's default options.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_preferences_remove_favorite_identity (kim_preferences  io_preferences,
kim_identity  in_identity 
)
+
+
+ +

+Remove a favorite identity from a preferences object. +

+

Parameters:
+ + + +
io_preferences a preferences object.
in_identity an identity to remove from io_preferences.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_preferences_remove_all_favorite_identities (kim_preferences  io_preferences  ) 
+
+
+ +

+Remove all favorite identities in a preferences object. +

+

Parameters:
+ + +
io_preferences a preferences object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_preferences_synchronize (kim_preferences  in_preferences  ) 
+
+
+ +

+Synchronize a preferences object with the user's preferences, writing pending changes and reading any changes applied by other processes. +

+

Parameters:
+ + +
in_preferences a preferences object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_preferences_free (kim_preferences io_preferences  ) 
+
+
+ +

+Free memory associated with a preferences object. +

+

Parameters:
+ + +
io_preferences the preferences object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__selection__hints__reference.html b/krb5-1-7/doc/kim/html/group__kim__selection__hints__reference.html new file mode 100644 index 000000000..a80eb7347 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__selection__hints__reference.html @@ -0,0 +1,751 @@ + + +Kerberos Identity Management: KIM Selection Hints Reference Documentation + + + + +

KIM Selection Hints Reference Documentation

+

+

Defines

+ +

Functions

+ +

Define Documentation

+ +
+
+ + + + +
#define kim_hint_key_client_realm   "kim_hint_key_client_realm"
+
+
+ +

+A client identity in this realm. See KIM Selection Hints Overview for more information +

+

+ +

+
+ + + + +
#define kim_hint_key_user   "kim_hint_key_user"
+
+
+ +

+A client identity whose first component is this user string. See KIM Selection Hints Overview for more information +

+

+ +

+
+ + + + +
#define kim_hint_key_service_realm   "kim_hint_key_service_realm"
+
+
+ +

+A client identity which has obtained a service credential for this realm. See KIM Selection Hints Overview for more information +

+

+ +

+
+ + + + +
#define kim_hint_key_service   "kim_hint_key_service"
+
+
+ +

+A client identity which has obtained a service credential for this service. See KIM Selection Hints Overview for more information +

+

+ +

+
+ + + + +
#define kim_hint_key_server   "kim_hint_key_server"
+
+
+ +

+A client identity which has obtained a service credential for this server. See KIM Selection Hints Overview for more information +

+

+ +

+
+ + + + +
#define kim_hint_key_service_identity   "kim_hint_key_service_identity"
+
+
+ +

+The client identity which has obtained a service credential for this service identity. See KIM Selection Hints Overview for more information +

+

+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_create (kim_selection_hints out_selection_hints,
kim_string  in_application_identifier 
)
+
+
+ +

+Create a new selection hints object. +

+

Parameters:
+ + + +
out_selection_hints on exit, a new selection hints object. Must be freed with kim_selection_hints_free().
in_application_identifier an application identifier string. Java-style identifiers are recommended to avoid cache entry collisions (eg: "com.example.MyApplication")
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_copy (kim_selection_hints out_selection_hints,
kim_selection_hints  in_selection_hints 
)
+
+
+ +

+Copy a selection hints object. +

+

Parameters:
+ + + +
out_selection_hints on exit, a new selection hints object which is a copy of in_selection_hints. Must be freed with kim_selection_hints_free().
in_selection_hints a selection hints object.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_set_hint (kim_selection_hints  io_selection_hints,
kim_string  in_hint_key,
kim_string  in_hint_string 
)
+
+
+ +

+Set the string value of a hint used for identity selection. +

+

Parameters:
+ + + + +
io_selection_hints a selection hints object to modify.
in_hint_key A string representing the type of hint to set.
in_hint_string A string representation of a hint for in_hint_key to set in in_selection_hints.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_get_hint()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_hint (kim_selection_hints  in_selection_hints,
kim_string  in_hint_key,
kim_string out_hint_string 
)
+
+
+ +

+Get the string value of a hint used for identity selection. +

+

Parameters:
+ + + + +
in_selection_hints a selection hints object.
in_hint_key A string representing the type of hint to obtain.
out_hint_string On exit, a string representation of the hint in_hint_key in in_selection_hints. If the hint is not set, sets the value pointed to by out_hint_string to NULL; Must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_set_hint()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_set_explanation (kim_selection_hints  io_selection_hints,
kim_string  in_explanation 
)
+
+
+ +

+Set the strings used to prompt the user to select the identity. +

+

Parameters:
+ + + +
io_selection_hints a selection hints object to modify.
in_explanation a localized string describing why the caller needs the identity.
+
+
Note:
If the application only does one thing (the reason it needs an identity is obvious) then you may not need to call this function.
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_get_explanation()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_explanation (kim_selection_hints  in_selection_hints,
kim_string out_explanation 
)
+
+
+ +

+Get the strings used to prompt the user to select the identity. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object.
out_explanation on exit, the localized string specified in in_selection_hints which describes why the caller needs the identity. May be NULL. If non-NULL, must be freed with kim_string_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_set_explanation()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_set_options (kim_selection_hints  io_selection_hints,
kim_options  in_options 
)
+
+
+ +

+Set the options which will be used if credentials need to be acquired. +

+

Parameters:
+ + + +
io_selection_hints a selection hints object to modify.
in_options options to control credential acquisition.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_get_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_options (kim_selection_hints  in_selection_hints,
kim_options out_options 
)
+
+
+ +

+Get the options which will be used if credentials need to be acquired. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object.
out_options on exit, the options to control credential acquisition specified in in_selection_hints. May be KIM_OPTIONS_DEFAULT. If not, must be freed with kim_options_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
See also:
kim_selection_hints_set_options()
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_set_allow_user_interaction (kim_selection_hints  in_selection_hints,
kim_boolean  in_allow_user_interaction 
)
+
+
+ +

+Set whether or not KIM may interact with the user to select an identity. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object to modify
in_allow_user_interaction a boolean value specifying whether or not KIM should ask the user to select an identity for in_selection_hints.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This setting defaults to TRUE.
+
See also:
kim_selection_hints_get_allow_user_interaction
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_allow_user_interaction (kim_selection_hints  in_selection_hints,
kim_boolean out_allow_user_interaction 
)
+
+
+ +

+Get whether or not KIM may interact with the user to select an identity. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object to modify
out_allow_user_interaction on exit, a boolean value specifying whether or not KIM should ask the user to select an identity for in_selection_hints.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This setting defaults to TRUE.
+
See also:
kim_selection_hints_set_allow_user_interaction
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_set_remember_identity (kim_selection_hints  in_selection_hints,
kim_boolean  in_remember_identity 
)
+
+
+ +

+Set whether or not KIM will use cached mappings for this selection hints object. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object to modify
in_remember_identity a boolean value specifying whether or not KIM should use a cached mapping between in_selection_hints and a Kerberos identity.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This setting defaults to TRUE.
+
See also:
kim_selection_hints_get_remember_identity
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_remember_identity (kim_selection_hints  in_selection_hints,
kim_boolean out_remember_identity 
)
+
+
+ +

+Get whether or not KIM will use cache mappings for this selection hints object. +

+

Parameters:
+ + + +
in_selection_hints a selection hints object to modify
out_remember_identity on exit, a boolean value specifying whether or not KIM will use a cached mapping between in_selection_hints and a Kerberos identity.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
This setting defaults to TRUE.
+
See also:
kim_selection_hints_set_remember_identity
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_get_identity (kim_selection_hints  in_selection_hints,
kim_identity out_identity 
)
+
+
+ +

+Choose a client identity based on selection hints. +

+

Parameters:
+ + + +
in_selection_hints the selection hints to add to the cache.
out_identity the Kerberos identity in_selection_hints maps to. Must be freed with kim_identity_free().
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+
Note:
out_identity is the identity mapped to by the current state of in_selection_hints. This function may prompt the user via a GUI to choose that identity. Subsequent modifications to in_selection_hints will not change out_identity.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_selection_hints_remember_identity (kim_selection_hints  in_selection_hints,
kim_identity  in_identity 
)
+
+
+ +

+Add an entry for the selection hints to the selection hints cache, replacing any existing entry. +

+

Parameters:
+ + + +
in_selection_hints the selection hints to add to the cache.
in_identity the Kerberos identity in_selection_hints maps to.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
kim_error kim_selection_hints_forget_identity (kim_selection_hints  in_selection_hints  ) 
+
+
+ +

+Remove an entry for the selection hints from the selection hints cache. +

+

Parameters:
+ + +
in_selection_hints the selection hints to remove from the cache.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_selection_hints_free (kim_selection_hints io_selection_hints  ) 
+
+
+ +

+Free memory associated with a selection hints object. +

+

Parameters:
+ + +
io_selection_hints the selection hints object to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__string__reference.html b/krb5-1-7/doc/kim/html/group__kim__string__reference.html new file mode 100644 index 000000000..31192c96f --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__string__reference.html @@ -0,0 +1,171 @@ + + +Kerberos Identity Management: KIM String Reference Documentation + + + + +

KIM String Reference Documentation

+

+

Functions

+ +

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_string_create_for_last_error (kim_string out_string,
kim_error  in_error 
)
+
+
+ +

+Get a text description of an error suitable for display to the user. +

+

Parameters:
+ + + +
out_string On success, a human-readable UTF-8 string describing the error representedby in_error. Must be freed with kim_string_free().
in_error an error code. Used to verify that the correct error string will be returned (see note below).
+
+
Returns:
On success, KIM_NO_ERROR.
+
Note:
This API is implemented using thread local storage. It should be called immediately after a KIM API returns an error code so that the correct string is returned. The returned copy may then be held by the caller until needed. If in_error does not match the last saved error KIM may return a less descriptive string.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
kim_error kim_string_copy (kim_string out_string,
const kim_string  in_string 
)
+
+
+ +

+Copy a string. +

+

Parameters:
+ + + +
out_string on exit, a new string object which is a copy of in_string. Must be freed with kim_string_free().
in_string the string to copy.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
kim_error kim_string_compare (kim_string  in_string,
kim_string  in_compare_to_string,
kim_comparison out_comparison 
)
+
+
+ +

+Compare two strings. +

+

Parameters:
+ + + + +
in_string a string.
in_compare_to_string a string to be compared to in_string.
out_comparison on exit, a comparison result indicating whether in_string is greater than, less than or equal to in_compare_to_string.
+
+
Returns:
On success, KIM_NO_ERROR. On failure, an error code representing the failure.
+ +
+

+ +

+
+ + + + + + + + + +
void kim_string_free (kim_string io_string  ) 
+
+
+ +

+Free memory associated with a string. +

+

Parameters:
+ + +
io_string a string to be freed. Set to NULL on exit.
+
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/group__kim__types__reference.html b/krb5-1-7/doc/kim/html/group__kim__types__reference.html new file mode 100644 index 000000000..a3c037609 --- /dev/null +++ b/krb5-1-7/doc/kim/html/group__kim__types__reference.html @@ -0,0 +1,454 @@ + + +Kerberos Identity Management: KIM Types and Constants + + + + +

KIM Types and Constants

+

+

Defines

+ +

Typedefs

+ +

Enumerations

+
    +
  • enum kim_credential_state_enum {
    +  kim_credentials_state_valid = 0, +kim_credentials_state_expired = 1, +kim_credentials_state_not_yet_valid = 2, +kim_credentials_state_needs_validation = 3, +
    +  kim_credentials_state_address_mismatch = 4 +
    + } +
+

Define Documentation

+ +
+
+ + + + +
#define KIM_IDENTITY_ANY   ((kim_identity) NULL)
+
+
+ +

+Constant to specify any Kerberos identity is acceptable. +

+

+ +

+
+ + + + +
#define KIM_OPTIONS_DEFAULT   ((kim_options) NULL)
+
+
+ +

+Specifies the user's default options. +

+

+ +

+
+ + + + +
#define KIM_OPTIONS_START_IMMEDIATELY   ((kim_time_t) 0)
+
+
+ +

+Specifies that credentials should be valid immediately. +

+

+ +

+
+ + + + +
#define KIM_NO_ERROR   ((kim_error) 0)
+
+
+ +

+No error value for the kim_error type. +

+

+ +

+
+ + + + + + + + + +
#define kim_comparison_is_less_than (  )    (c < 0)
+
+
+ +

+Convenience macro for interpreting kim_comparison. +

+

+ +

+
+ + + + + + + + + +
#define kim_comparison_is_equal_to (  )    (c == 0)
+
+
+ +

+Convenience macro for interpreting kim_comparison. +

+

+ +

+
+ + + + + + + + + +
#define kim_comparison_is_greater_than (  )    (c > 0)
+
+
+ +

+Convenience macro for interpreting kim_comparison. +

+

+


Typedef Documentation

+ +
+
+ + + + +
typedef int kim_credential_state
+
+
+ +

+The state of a credential. See kim_credential_state_enum for possible values. +

+

+ +

+
+ + + + +
typedef int32_t kim_error
+
+
+ +

+The KIM Error type. +

+

+ +

+
+ + + + +
typedef int64_t kim_time
+
+
+ +

+A time value represented in seconds since January 1, 1970. +

+

+ +

+
+ + + + +
typedef int64_t kim_lifetime
+
+
+ +

+A duration represented in seconds. +

+

+ +

+
+ + + + +
typedef uint64_t kim_count
+
+
+ +

+An quantity, usually used to return the number of elements in an array. +

+

+ +

+
+ + + + +
typedef int kim_boolean
+
+
+ +

+A boolean value. 0 means false, all other values mean true. +

+

+ +

+
+ + + + +
typedef int kim_comparison
+
+
+ +

+A comparison between two sortable objects.

+ +
+

+ +

+
+ + + + +
typedef const char* kim_string
+
+
+ +

+The KIM String type. See KIM String Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_identity_opaque* kim_identity
+
+
+ +

+A KIM Principal object. See KIM Identity Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_options_opaque* kim_options
+
+
+ +

+A KIM Options object. See KIM Options Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_selection_hints_opaque* kim_selection_hints
+
+
+ +

+A KIM Selection Hints object. See KIM Selection Hints Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_preferences_opaque* kim_preferences
+
+
+ +

+A KIM Preferences object. See KIM Preferences Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_ccache_iterator_opaque* kim_ccache_iterator
+
+
+ +

+A KIM CCache Iterator object. See Acquiring a CCache from the Cache Collection for more information. +

+

+ +

+
+ + + + +
typedef struct kim_ccache_opaque* kim_ccache
+
+
+ +

+A KIM CCache object. See KIM CCache Overview for more information. +

+

+ +

+
+ + + + +
typedef struct kim_credential_iterator_opaque* kim_credential_iterator
+
+
+ +

+A KIM Credential Iterator object. See Iterating over the Credentials in a CCache for more information. +

+

+ +

+
+ + + + +
typedef struct kim_credential_opaque* kim_credential
+
+
+ +

+A KIM Credential object. See KIM Credential Overview for more information. +

+

+


Enumeration Type Documentation

+ +
+
+ + + + +
enum kim_credential_state_enum
+
+
+ +

+Possible credential states. Credentials may be:

    +
  • valid - The credential can be used.
  • +
  • expired - The credential's lifetime has been exceeded.
  • +
  • not_yet_valid - The credential is post dated and the time when it becomes valid has not yet been reached.
  • +
  • needs_validation - The credential is post-dated and although the time when it becomes valid has been reached it has not yet been validated.
  • +
  • address_mismatch - The credential contains IP address(es) which do not match the host's local address(es).
  • +
+ +
+

+


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/index.html b/krb5-1-7/doc/kim/html/index.html new file mode 100644 index 000000000..a11d58f64 --- /dev/null +++ b/krb5-1-7/doc/kim/html/index.html @@ -0,0 +1,83 @@ + + +Kerberos Identity Management: Kerberos Identity Management (KIM) API Documentation + + + + +

Kerberos Identity Management (KIM) API Documentation

+

+

+Introduction

+The Kerberos Identity Management API is a high level API for managing the selection and management of Kerberos credentials. It is intended for use by applications, credential management applications (eg: kinit, kpasswd, etc) and internally by the Kerberos libraries. Under some circumstances client applications may also benefit from the Kerberos Identity Management API.

+API Conventions

+Although KIM currently only provides a C API, it attempts to make that API as object-oriented as possible. KIM functions are grouped by object and all of the object types are opaque, including errors. The reason for this is two-fold. First, the KIM API is rather large. Grouping functions by object allows the API to be broken up into smaller, more manageable chunks. Second, providing an object-like C API will make it easier to port to object oriented languages.

+Because C lacks classes and other object oriented syntax, KIM functions adhere to the following naming conventions to make functions easier to identify:

+

    +
  • Functions beginning with kim_object_create are constructors for an object of type kim_object. On success these functions return a newly allocated object which must later be freed by the caller.
  • +
+
    +
  • Functions of the form kim_object_copy are copy constructors. They instantiate a new object of kim_object from an object of the same type.
  • +
+
    +
  • Functions of the form kim_object_free are destructors for objects of type kim_object.
  • +
+
    +
  • Functions beginning with kim_object_get and kim_object_set examine and modify properties of objects of type kim_object.
  • +
+
    +
  • All KIM APIs except destructors and error management APIs return a KIM Error object (kim_error_t).
  • +
+

+Terminology

+Kerberos organizes its authentication tokens by client identity (the name of the user) and service identity (the name of a service). The following terms are used throughout this documentation:

+

    +
  • credential - A token which authenticates a client identity to a service identity.
  • +
+
    +
  • ccache - Short for "credentials cache". A set of credentials for a single client identity.
  • +
+
    +
  • cache collection - The set of all credential caches.
  • +
+
    +
  • default ccache - A credentials cache that the Kerberos libraries will use if no ccache is specified by the caller. Use of the default ccache is now discouraged. Instead applications should use selection hints to choose an appropriate client identity.
  • +
+

+Client Identity Selection APIs

+KIM provides high level APIs for applications to select which client identity to use. Use of these APIs is intended to replace the traditional "default ccache" mechanism previously used by Kerberos.

+KIM Selection Hints (kim_selection_hints_t) controls options for selecting a client identity:

+

+KIM Identity (kim_identity_t) provides an immutable Kerberos identity object

+

+Credential Management APIs

+KIM also provides APIs for acquiring new credentials over the network by contacting a KDC and for viewing and modifying the existing credentials in the cache collection

+Whether or not you use the credential or ccache APIs depends on whether you want KIM to store any newly acquired credentials in the cache collection. KIM ccache APIs always create a ccache in the cache collection containing newly acquired credentials whereas the KIM credential APIs just return a credential object. In general most callers want to store newly acquired credentials and should use the KIM ccache APIs when acquiring credentials.

+KIM CCache (kim_ccache_t) manipulates credential caches in the cache collection:

+

+KIM Credential (kim_credential_t) manipulates credentials:

+

+KIM Options (kim_options_t) control options for credential acquisition:

+

+KIM Preferences (kim_preferences_t) views and edits the current user's preferences:

+

+Miscellaneous APIs

+The high and low level APIs depend on the following basic utility classes to manage generic types.

+KIM String (kim_string_t) provides memory management for an immutable string:

+

+Types and Constants

+ +
Generated on Mon Nov 3 17:45:43 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_ccache_overview.html b/krb5-1-7/doc/kim/html/kim_ccache_overview.html new file mode 100644 index 000000000..e6cce0abe --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_ccache_overview.html @@ -0,0 +1,70 @@ + + +Kerberos Identity Management: KIM CCache Overview + + + + +

KIM CCache Overview

+Introduction

+Kerberos credentials are stored in "ccaches" (short for "credentials caches"). The set of all ccaches which the KIM can use is called the "cache collection". Each ccache has a name and type which uniquely identify it in the cache collection and a client identity. The ccache's client identity is the identity whose credentials are stored in the ccache. This allows for easy lookup of all the credentials for a given identity.

+KIM attempts to preserve a one-to-one relationship between client identities and ccaches. If the KIM is used to manipulate the cache collection, there will be one ccache per identity. However, because low-level APIs allow callers to create multiple ccaches for the same client identity or a single ccache containing credentials for different client identities, KIM handles those situations. In general when searching KIM will find the first ccache matching the requested client identity. It will not find credentials for the requested client identity if they are in a ccache with a different client identity.

+The kim_ccache_t object is a reference to a ccache in the cache collection. If other applications make changes to the the ccache pointed to by a KIM ccache object, the object will immediately show those changes. KIM performs locking on the cache collection to prevent deadlocks and maintain a consistent behavior when multiple applications attempt to modify the cache collection.

+

Note:
KIM ccache APIs are intended for applications and system tools which manage credentials for the user. They are not a substitute for krb5 and GSSAPI functions which obtain service credentials for the purpose of authenticating a client to an application server.
+

+Acquiring a CCache from the Cache Collection

+KIM provides a simple iterator API for iterating over the ccaches in the cache collection. First, call kim_ccache_iterator_create() to obtain an iterator for the cache collection. Then loop calling kim_ccache_iterator_next() until either you find the ccache you are looking for or the API returns a NULL ccache, indicating that there are no more ccaches in the cache collection. When you are done with the iterator, call kim_ccache_iterator_free().

+

Note:
kim_ccache_iterator_next() returns ccache objects which must be freed with kim_ccache_free() to avoid leaking memory.
+KIM also provides a convenient API kim_ccache_create_from_client_identity() which returns the ccache for a specific client identity, if any exists. Typically callers of this API obtain the client identity using kim_selection_hints_get_identity().

+Acquiring Credentials from the Default CCache

+kim_ccache_create_from_default() returns the default ccache. The default ccache is a legacy concept which was replaced by selection hints. Prior to the existence of selection hints, applications always looked at the default ccache for credentials. By setting the system default ccache, users could manually control which credentials each application used. As the number of ccaches and applications has grown, this mechanism has become unusable. You should avoid using this API whenever possible.

+Acquiring New Credentials in a CCache

+KIM provides the kim_ccache_create_new() API for acquiring new credentials and storing them in a ccache. Credentials can either be obtained for a specific client identity or by specifying KIM_IDENTITY_ANY to allow the user to choose. Typically callers of this API obtain the client identity using kim_selection_hints_get_identity(). Depending on the kim_options specified, kim_ccache_create_new() may present a GUI or command line prompt to obtain information from the user.

+kim_ccache_create_new_if_needed() searches the cache collection for a ccache for the client identity and if no appropriate ccache is available, attempts to acquire new credentials and store them in a new ccache. Depending on the kim_options specified, kim_ccache_create_new_if_needed() may present a GUI or command line prompt to obtain information from the user. This function exists for convenience and to avoid code duplication. It can be trivially implemented using kim_ccache_create_from_client_identity() and kim_ccache_create_new().

+For legacy password-based Kerberos environments KIM also provides kim_ccache_create_new_with_password() and kim_ccache_create_new_if_needed_with_password(). You should not use these functions unless you know that they will only be used in environments using passwords. Otherwise users without passwords may be prompted for them.

+KIM provides the kim_ccache_create_from_keytab() to create credentials using a keytab and store them in the cache collection. A keytab is an on-disk copy of a client identity's secret key. Typically sites use keytabs for client identities that identify a machine or service and protect the keytab with disk permissions. Because a keytab is sufficient to obtain credentials, keytabs will normally only be readable by root, Administrator or some other privileged account. Typically applications use credentials obtained from keytabs to obtain credentials for batch processes. These keytabs and credentials are usually for a special identity used for the batch process rather than a user identity.

+Validating Credentials in a CCache

+A credential with a start time in the future (ie: after the issue date) is called a post-dated credential. Because the KDC administrator may wish to disable a identity, once the start time is reached, all post-dated credentials must be validated before they can be used. Otherwise an attacker using a compromised account could acquire lots of post-dated credentials to circumvent the acccount being disabled.

+KIM provides the kim_ccache_validate() API to validate the TGT credential in a ccache. Note that this API replaces any existing credentials with the validated credential.

+Renewing Credentials in a CCache

+A renewable credential can be used to obtain a new identical credential without resending secret information (such as a password) to the KDC. A credential may only be renewed during its renewal lifetime and while valid.

+KIM provides the kim_ccache_renew() API to renew the TGT credential in a ccache. Note that this API replaces any existing credentials with the renewed credential.

+Verifying Credentials in a CCache

+When a program acquires TGT credentials for the purpose of authenticating itself to the machine it is running on, it is insufficient for the machine to assume that the caller is authorized just because it got credentials. Instead, the credentials must be verified using a key the local machine. The reason this is necessary is because an attacker can trick the machine into obtaining credentials from any KDC, including malicious ones with the same realm name as the local machine's realm. This exploit is called the Zanarotti attack.

+In order to avoid the Zanarotti attack, the local machine must authenticate the process in the same way an application server would authenticate a client. Like an application server, the local machine must have its own identity in its realm and a keytab for that identity on its local disk. However, rather than forcing system daemons to use the network-oriented calls in the krb5 and GSS APIs, KIM provides the kim_ccache_verify() API to verify credentials directly.

+The most common reason for using kim_ccache_verify() is user login. If the local machine wants to use Kerberos to verify the username and password provided by the user, it must call kim_ccache_verify() on the credentials it obtains to make sure they are really from a KDC it trusts. Another common case is a server which is only using Kerberos internally. For example an LDAP or web server might use a username and password obtained over the network to get Kerberos credentials. In order to make sure they aren't being tricked into talking to the wrong KDC, these servers must also call kim_ccache_verify().

+The Zanarotti attack is only a concern if the act of accessing the machine gives the process special access. Thus a managed cluster machine with Kerberos-authenticated networked home directories does not need to call kim_ccache_verify(). Even though an attacker can log in as any user on the cluster machine, the attacker can't actually access any of the user's data or use any of their privileges because those are all authenticated via Kerberized application servers (and thus require actually having credentials for the real local realm).

+kim_ccache_verify() provides an option to return success even if the machine's host key is not present. This option exists for sites which have a mix of different machines, some of which are vulnerable to the Zanarotti attack and some are not. If this option is used, it is the responsiblity of the machine's maintainer to obtain a keytab for their machine if it needs one.

+Examining CCache Properties

+
    +
  • kim_ccache_get_type() returns the type of the ccache. Types include "API" for CCAPI ccaches, "FILE" for file-based ccaches and "MEMORY" for single-process in-memory ccaches.
  • +
+
    +
  • kim_ccache_get_name() returns the name of the ccache. A ccache's name identifies the ccache uniquely among ccaches of the same type. Note that two ccaches with different types may have the same name.
  • +
+
    +
  • kim_ccache_get_display_name() returns a display string which uniquely identifies a ccache. A ccache display name is of the form "<type>:<name>" and can be displayed to the user or used as an argument to certain krb5 APIs, such as krb5_cc_resolve().
  • +
+ +
    +
  • kim_ccache_get_valid_credential() returns the first valid TGT in the ccache for its client identity. If there are no TGTs in the ccache, it returns the first valid non-TGT credential for the ccache's client identity. TGT credentials (ie: "ticket-granting tickets") are credentials for the krbtgt service: a service identity of the form "krbtgt/<REALM>@<REALM>". These credentials allow the entity named by the client identity to obtain additional credentials without resending shared secrets (such as a password) to the KDC. Kerberos uses TGTs to provide single sign-on authentication.
  • +
+
    +
  • kim_ccache_get_start_time() returns when the credential's in a ccache will become valid. Credentials may be "post-dated" which means that their lifetime starts sometime in the future. Note that when a post-dated credential's start time is reached, the credential must be validated. See Validating Credentials for more information.
  • +
+
    +
  • kim_ccache_get_expiration_time() returns when the credential's in a ccache will expire. Credentials are time limited by the lifetime of the credential. While you can request a credential of any lifetime, the KDC limits the credential lifetime to a administrator-defined maximum. Typically credential lifetime range from 10 to 21 hours.
  • +
+
    +
  • kim_ccache_get_renewal_expiration_time() returns when the credential's in a ccache will no longer be renewable. Valid credentials may be renewed up until their renewal expiration time. Renewing credentials acquires a fresh set of credentials with a full lifetime without resending secrets to the KDC (such as a password). If credentials are not renewable, this function will return an error.
  • +
+
    +
  • kim_ccache_get_options() returns a kim_options object with the credential options of the credentials in the ccache. This function is intended to be used when adding an identity with existing credentials to the favorite identities list. By passing in the options returned by this call, future requests for the favorite identity will use the same credential options.
  • +
+See KIM CCache Reference Documentation and KIM CCache Iterator Reference Documentation for information on specific APIs.
Generated on Mon Nov 3 17:45:43 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_credential_overview.html b/krb5-1-7/doc/kim/html/kim_credential_overview.html new file mode 100644 index 000000000..71f981777 --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_credential_overview.html @@ -0,0 +1,67 @@ + + +Kerberos Identity Management: KIM Credential Overview + + + + +

KIM Credential Overview

+Introduction

+A Kerberos credential (also called a "Kerberos ticket") is a time-limited token issued by a KDC which authenticates the entity named by the credential's client identity to the service named by the credential's service identity.

+The kim_credential object contains a single Kerberos credential. KIM credentials objects are always copies of credentials, not references to credentials stored in the cache collection. Modifying credential objects in the ccache collection will not change any existing KIM credential objects.

+KIM credential APIs are intended for applications and system tools which manage credentials for the user. They are not a substitute for krb5 and GSSAPI functions which obtain service credentials for the purpose of authenticating a client to an application server.

+

Note:
Many of the APIs listed below have equivalent functions which operate on ccaches. In most cases applications will want to use the ccache versions of these APIs since they automatically store any newly created credentials. See KIM CCache Overview for more information.
+

+Acquiring New Credentials

+KIM provides the kim_credential_create_new() API for acquiring new credentials. Credentials can either be obtained for a specific client identity or by specifying KIM_IDENTITY_ANY to allow the user to choose. Typically callers of this API obtain the client identity using kim_selection_hints_get_identity(). Depending on the kim_options specified, kim_credential_create_new() may present a GUI or command line prompt to obtain information from the user.

+For legacy password-based Kerberos environments KIM also provides kim_credential_create_new_with_password(). You should not use this function unless you know that it will only be used in environments using passwords. Otherwise users without passwords may be prompted for them.

+KIM provides the kim_credential_create_from_keytab() to create credentials using a keytab. A keytab is an on-disk copy of a client identity's secret key. Typically sites use keytabs for client identities that identify a machine or service and protect the keytab with disk permissions. Because a keytab is sufficient to obtain credentials, keytabs will normally only be readable by root, Administrator or some other privileged account. Typically applications use credentials obtained from keytabs to obtain credentials for batch processes. These keytabs and credentials are usually for a special identity used for the batch process rather than a user identity.

+Validating Credentials

+A credential with a start time in the future (ie: after the issue date) is called a post-dated credential. Because the KDC administrator may wish to disable a identity, once the start time is reached, all post-dated credentials must be validated before they can be used. Otherwise an attacker using a compromised account could acquire lots of post-dated credentials to circumvent the acccount being disabled.

+KIM provides the kim_credential_validate() API to validate a credential. Note that this API replaces the credential object with a new validated credential object. If you wish to store the new credential in the ccache collection you must either call kim_credential_store() on the validated credential or use kim_ccache_validate() instead.

+Renewing Credentials

+A renewable credential can be used to obtain a new identical credential without resending secret information (such as a password) to the KDC. A credential may only be renewed during its renewal lifetime and while valid.

+KIM provides the kim_credential_renew() API to renew a credential. Note that this API replaces the credential object with a new renewed credential object. If you wish to store the new credential in the ccache collection you must either call kim_credential_store() on the renewed credential or use kim_ccache_renew() instead.

+Storing Credentials in the Cache Collection

+KIM credential objects may be stored in the ccache collection using kim_credential_store(). This function runs any KIM authentication plugins on the credential and if the plugins return successfully, creates a new ccache for the credential's client identity in the cache collection and stores the credential in that ccache. Any existing ccaches and credentials for that client identity will be overwritten. kim_credential_store() may optionally return a kim_ccache object for the new ccache if you need to perform further operations on the new ccache.

+Most of the time if you plan to store the credentials you are manipulating, you should use one of KIM ccache APIs. These functions perform the same operations except that they also call kim_credential_store() any time the credential object changes. See KIM CCache Overview for more information.

+Iterating over the Credentials in a CCache

+KIM provides a simple iterator API for iterating over the credentials in a ccache. First, call kim_credential_iterator_create() to obtain an iterator for a ccache. Then loop calling kim_credential_iterator_next() until either you find the credential you are looking for or the API returns a NULL credential, indicating that there are no more credentials in the ccache. When you are done with the iterator, call kim_credential_iterator_free().

+

Note:
kim_credential_iterator_next() returns credential objects which must be freed with kim_credential_free() to avoid leaking memory.
+

+Verifying Credentials

+When a program acquires TGT credentials for the purpose of authenticating itself to the machine it is running on, it is insufficient for the machine to assume that the caller is authorized just because it got credentials. Instead, the credentials must be verified using a key the local machine. The reason this is necessary is because an attacker can trick the machine into obtaining credentials from any KDC, including malicious ones with the same realm name as the local machine's realm. This exploit is called the Zanarotti attack.

+In order to avoid the Zanarotti attack, the local machine must authenticate the process in the same way an application server would authenticate a client. Like an application server, the local machine must have its own identity in its realm and a keytab for that identity on its local disk. However, rather than forcing system daemons to use the network-oriented calls in the krb5 and GSS APIs, KIM provides the kim_credential_verify() API to verify credentials directly.

+The most common reason for using kim_credential_verify() is user login. If the local machine wants to use Kerberos to verify the username and password provided by the user, it must call kim_credential_verify() on the credentials it obtains to make sure they are really from a KDC it trusts. Another common case is a server which is only using Kerberos internally. For example an LDAP or web server might use a username and password obtained over the network to get Kerberos credentials. In order to make sure they aren't being tricked into talking to the wrong KDC, these servers must also call kim_credential_verify().

+The Zanarotti attack is only a concern if the act of accessing the machine gives the process special access. Thus a managed cluster machine with Kerberos-authenticated networked home directories does not need to call kim_credential_verify(). Even though an attacker can log in as any user on the cluster machine, the attacker can't actually access any of the user's data or use any of their privileges because those are all authenticated via Kerberized application servers (and thus require actually having credentials for the real local realm).

+kim_credential_verify() provides an option to return success even if the machine's host key is not present. This option exists for sites which have a mix of different machines, some of which are vulnerable to the Zanarotti attack and some are not. If this option is used, it is the responsiblity of the machine's maintainer to obtain a keytab for their machine if it needs one.

+Examining Credential Properties

+ + +
    +
  • kim_credential_is_tgt() returns whether the credential is a TGT (ie: "ticket-granting ticket"). TGTs are credentials for the krbtgt service: a service identity of the form "krbtgt/<REALM>@<REALM>". These credentials allow the entity named by the client identity to obtain additional service credentials without resending shared secrets (such as a password) to the KDC. Kerberos uses TGTs to provide single sign-on authentication.
  • +
+
    +
  • kim_credential_get_state() returns a kim_credential_state containing the state of the credential. Possible values are: * kim_credentials_state_valid * kim_credentials_state_expired * kim_credentials_state_not_yet_valid * kim_credentials_state_needs_validation * kim_credentials_state_address_mismatch
  • +
+
    +
  • kim_credential_get_start_time() returns when the credential will become valid. Credentials may be "post-dated" which means that their lifetime starts sometime in the future. Note that when a post-dated credential's start time is reached, the credential must be validated. See Validating Credentials for more information.
  • +
+
    +
  • kim_credential_get_expiration_time() returns when the credential will expire. Credentials are time limited by the lifetime of the credential. While you can request a credential of any lifetime, the KDC limits the credential lifetime to a administrator-defined maximum. Typically credential lifetime range from 10 to 21 hours.
  • +
+
    +
  • kim_credential_get_renewal_expiration_time() returns when the credential will no longer be renewable. Valid credentials may be renewed up until their renewal expiration time. Renewing credentials acquires a fresh set of credentials with a full lifetime without resending secrets to the KDC (such as a password). If credentials are not renewable, this function will return a renewal expiration time of 0.
  • +
+
    +
  • kim_credential_get_options() returns a kim_options object with the credential options of the credential. This function is intended to be used when adding an identity with existing credentials to the favorite identities list. By passing in the options returned by this call, future requests for the favorite identity will use the same credential options.
  • +
+See KIM Credential Reference Documentation and KIM Credential Iterator Reference Documentation for information on specific APIs.
Generated on Mon Nov 3 17:45:43 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_error_overview.html b/krb5-1-7/doc/kim/html/kim_error_overview.html new file mode 100644 index 000000000..7a3f01844 --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_error_overview.html @@ -0,0 +1,16 @@ + + +Kerberos Identity Management: KIM Error Overview + + + + +

KIM Error Overview

Like most C APIs, the KIM API returns numeric error codes. These error codes may come from KIM, krb5 or GSS APIs. In most cases the caller will want to handle these error programmatically. However, in some circumstances the caller may wish to print an error string to the user.

+One problem with just printing the error code to the user is that frequently the context behind the error has been lost. For example if KIM is trying to obtain credentials via referrals, it may fail partway through the process. In this case the error code will be KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, which maps to "Client not found in Kerberos database". Unfortunately this error isn't terribly helpful because it doesn't tell the user whether they typoed their principal name or if referrals failed.

+To avoid this problem, KIM maintains an explanatory string for the last error seen in each thread calling into KIM. If a caller wishes to display an error to the user, immediately after getting the error the caller should call kim_string_get_last_error_message() to obtain a copy of the descriptive error message.

+Note that because this string is stored in thread-specific data, callers must call kim_string_get_last_error_message() before calling any KIM APIs or any other APIs which might call into KIM. Callers who are not going to display this error string immediately should also make a copy of it so that it is not overwritten by the next call into KIM.

+See KIM Error Reference Documentation for information on specific APIs.


Generated on Mon Sep 22 18:09:05 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_favorite_identities_overview.html b/krb5-1-7/doc/kim/html/kim_favorite_identities_overview.html new file mode 100644 index 000000000..ae5529d4d --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_favorite_identities_overview.html @@ -0,0 +1,24 @@ + + +Kerberos Identity Management: KIM Favorite Identities Overview + + + + +

KIM Favorite Identities Overview

+Introduction

+As Kerberos becomes more widespread, the number of possible Kerberos identities and realms a user might want to use will become very large. Sites may list hundreds of realms in their Kerberos configuration files. In addition, sites may wish to use DNS SRV records to avoid having to list all the realms they use in their Kerberos configuration. As a result, the list of realms in the Kerberos configuration may be exceedingly large and/or incomplete. Users may also use multiple identities from the same realm.

+On platforms which use a GUI to acquire credentials, the KIM would like to to display a list of identities for the user to select from. Depending on what is appropriate for the platform, identities may be displayed in a popup menu or other list.

+To solve this problem, the KIM maintains a list of favorite identities specifically for identity selection. This list is a set of unique identities in alphabetical order (as appropriate for the user's language localization).

+On most platforms the list of favorite identities has both an administrator preference and a user preference which overrides it. The administrator preference exists only to initialize the favorite identities for new user accounts. Once the user modifies the list their favorite identities may diverge from the site favorite identities preference.

+

Note:
The location of user preferences and the semantics of preference synchronization is platform-specific. Where possible KIM will use platform-specific preference mechanisms.
+Most callers will not need to use the favorite identities APIs. However if you are implementing your own graphical prompt callback or a credential management application, you may to view and/or edit the user's favorite identities.

+Viewing and Editing the Favorite Identities

+First, you need to acquire the Favorite Identities stored in the user's preferences using kim_preferences_create() and kim_preferences_get_favorite_identities(). Or you can use kim_favorite_identities_create() to get an empty identities list if you want to overwrite the user's identities list entirely. See KIM Preferences Overview for more information on modifying the user's preferences.

+Then use kim_favorite_identities_get_number_of_identities() and kim_favorite_identities_get_identity_at_index() to display the identities list. Use kim_favorite_identities_add_identity() and kim_favorite_identities_remove_identity() to change which identities are in the identities list. Identities are always stored in alphabetical order and duplicate identities are not permitted, so when you add or remove a identity you should redisplay the entire list.

+Once you are done editing the identities list, store changes in the user's preference file using kim_preferences_set_favorite_identities() and kim_preferences_synchronize().

+See KIM Favorite Identities Documentation for information on specific APIs.


Generated on Wed May 7 15:22:19 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_identity_overview.html b/krb5-1-7/doc/kim/html/kim_identity_overview.html new file mode 100644 index 000000000..a930d4321 --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_identity_overview.html @@ -0,0 +1,43 @@ + + +Kerberos Identity Management: KIM Identity Overview + + + + +

KIM Identity Overview

+Introduction

+Identities in Kerberos are named by "principals". These identies may be people (users) or services (a server running on a host). When Kerberos issues credentials which authenticate one identity to another, the identity being authenticated is called the "client identity" and the identity being authenticated to is called the "service identity".

+Kerberos identities are made up of one or more components, as well as the Kerberos realm the entity belongs to. For client identities the first component is usually the client username (eg: "jdoe"). For service identities the first component is the name of the service (eg: "imap").

+Kerberos identities have both a binary (opaque) representation and also a string representation. The string representation consists of the components separated by '/' followed by an '@' and then the realm. For example, the identity "jdoe/admin@EXAMPLE.COM" represents John Doe's administrator identity at the realm EXAMPLE.COM. Note that identity components may contain both '/' and '@' characters. When building a identity from its string representation these syntactic characters must be escaped with '\'.

+Creating and Displaying Identities

+KIM Identities can be generated from components, their escaped string representation or from a krb5_principal. Once you have a KIM identity object, you can also get the component, string or krb5_principal representations back out:

+

+ + +
Note:
If you need to know if two identity objects refer to the same entity, use kim_identity_compare().
+

+Choosing a Client Identity

+Unfortunately most of the time applications don't know what client identity to use. Users may have identities for multiple Kerberos realms, as well as multiple identities in a single realm (such as a user and administrator identity).

+To solve this problem, kim_selection_hints_get_identity() takes information from the application in the form of a selection hints object and returns the best matching client identity, if one is available. See KIM Selection Hints Overview for more information.

+Changing a Identity's Password

+Many Kerberos sites use passwords for user accounts. Because passwords may be stolen or compromised, they must be frequently changed. KIM provides APIs to change the identity's password directly, and also handles changing the identity's password when it has expired.

+kim_identity_change_password() presents a user interface to obtain the old and new passwords from the user.

+

Note:
Not all identities have a password. Some sites use certificates (pkinit) and in the future there may be other authentication mechanisms (eg: smart cards).
+See KIM Identity Reference Documentation for information on specific APIs.
Generated on Mon Nov 3 17:45:43 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_options_overview.html b/krb5-1-7/doc/kim/html/kim_options_overview.html new file mode 100644 index 000000000..993239836 --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_options_overview.html @@ -0,0 +1,40 @@ + + +Kerberos Identity Management: KIM Options Overview + + + + +

KIM Options Overview

+Introduction

+Kerberos Identity Management Options (kim_options_t) allows you to control how the Kerberos library obtains credentials. When the options structure is initialized with kim_options_create(), each option is filled in with a default value which can then be modified with the kim_options_set_*() APIs. If you only want to use the default values, you may pass KIM_OPTIONS_DEFAULT into any KIM function that takes a kim_options_t.

+KIM options fall into two major categories: options for controlling how credentials are acquired and options for controlling what properties the newly acquired credentials will have:

+Options for Controlling Credential Properties

+Kerberos credentials have a number of different properties which can be requested when credentials are acquired. These properties control when and for how long the credentials are valid and what you can do with them.

+Note that setting these properties in the KIM options only changes what the Kerberos libraries request from the KDC. The KDC itself may choose not to honor your requested properties if they violate the site security policy. For example, most sites place an upper bound on how long credentials may be valid. If you request a credential lifetime longer than this upper bound, the KDC may return credentials with a shorter lifetime than you requested.

+Credential Lifetime

+Kerberos credentials have start time and a lifetime during which they are valid. Once the lifetime has passed, credentials "expire" and can no longer be used.

+The requested credential start time can be set with kim_options_set_start_time() and examined with kim_options_get_start_time(). The requested credential lifetime can be set with kim_options_set_lifetime() and examined with kim_options_get_lifetime().

+Renewable Credentials

+Credentials with very long lifetimes are more convenient since the user does not have authenticate as often. Unfortunately they are also a higher security risk: if credentials are stolen they can be used until they expire. Credential renewal exists to compromise between these two conflicting goals.

+Renewable credentials are TGT credentials which can be used to obtain new TGT credentials without reauthenticating. By regularly renewing credentials the KDC has an opportunity to check to see if the client's credentials have been reported stolen and refuse to renew them. Renewable credentials have a "renewal lifetime" during which credentials can be renewed. This lifetime is relative to the original credential start time. If credentials are renewed shortly before the end of the renewal lifetime, their lifetime will be capped to the end of the renewal lifetime.

+Note that credentials must be valid to be renewed and therefore may not be an appropriate solution for all use cases. Sites which use renewable credentials often create helper processes running as the user which will automatically renew the user's credentials when they get close to expiration.

+Use kim_options_set_renewable() to change whether or not the Kerberos libraries request renewable credentials and kim_options_get_renewable() to find out the current setting. Use kim_options_set_renewal_lifetime() to change the requested renewal lifetime and kim_options_get_renewal_lifetime() to find out the current value.

+Addressless Credentials

+Traditionally Kerberos used the host's IP address as a mechanism to restrict the user's credentials to a specific host, thus making it harder to use stolen credentials. When authenticating to a remote service with credentials containing addresses, the remote service verifies that the client's IP address is one of the addresses listed in the credential. Unfortunately, modern network technologies such as NAT rewrite the IP address in transit, making it difficult to use credentials with addresses in them. As a result, most Kerberos sites now obtain addressless credentials.

+Use kim_options_set_addressless() to change whether or not the Kerberos libraries request addressless credentials. Use kim_options_get_addressless() to find out the current setting.

+Forwardable Credentials

+Forwardable credentials are TGT credentials which can be forwarded to a service you have authenticated to. If the credentials contain IP addresses, the addresses are changed to reflect the service's IP address. Credential forwarding is most commonly used for Kerberos-authenticated remote login services. By forwarding TGT credentials through the remote login service, the user's credentials will appear on the remote host when the user logs in.

+The forwardable flag only applies to TGT credentials.

+Use kim_options_set_forwardable() to change whether or not the Kerberos libraries request forwardable credentials. Use kim_options_get_forwardable() to find out the current setting.

+Proxiable Credentials

+Proxiable credentials are similar to forwardable credentials except that instead of forwarding the a TGT credential itself, a service credential is forwarded instead. Using proxiable credentials, a user can permit a service to perform a specific task as the user using one of the user's service credentials.

+Like forwardability, the proxiable flag only applies to TGT credentials. Unlike forwarded credentials, the IP address of proxiable credentials are not modified for the service when being proxied. This can be solved by also requesting addressless credentials.

+Use kim_options_set_proxiable() to change whether or not the Kerberos libraries request proxiable credentials. Use kim_options_get_proxiable() to find out the current setting.

+Service Name

+Normally users acquire TGT credentials (ie "ticket granting tickets") and then use those credentials to acquire service credentials. This allows Kerberos to provide single sign-on while still providing mutual authentication to services. However, sometimes you just want an initial credential for a service. KIM options allows you to set the service name with kim_options_set_service_name() and query it with kim_options_get_service_name().

+See KIM Options Reference Documentation for information on specific APIs.


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_preferences_overview.html b/krb5-1-7/doc/kim/html/kim_preferences_overview.html new file mode 100644 index 000000000..2759f594c --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_preferences_overview.html @@ -0,0 +1,36 @@ + + +Kerberos Identity Management: KIM Preferences Overview + + + + +

KIM Preferences Overview

+Introduction

+In addition to the site preferences stored in the Kerberos configuration, users may also want to have their own personal preferences for controlling credential acquisition. As a result, KIM provides user preferences for initial credential options and user interface behavior such as the default client identity and the favorite identities list.

+Viewing and Editing the Preferences

+In order to view and edit the user's preferences, call kim_preferences_create() to acquire a preferences object containing the user's preferences. You can examine preferences with the functions starting with "kim_preferences_get_" and change preferences with the functions starting with "kim_preferences_set_". Once you are done making changes, you can write changes back out to the user's preferences with kim_preferences_synchronize().

+

Note:
The location of user preferences and the semantics of preference synchronization is platform-specific. Where possible KIM will use platform-specific preference mechanisms.
+

+Initial Credential Options Preferences

+KIM provides user preferences for initial credential options. These are the options kim_options_create() will use when creating a new KIM options object. They are also the options specified by KIM_OPTIONS_DEFAULT. You can view and edit the initial credential options using kim_preferences_get_options() and kim_preferences_set_options().

+

Note:
Not all credential options in the kim_options_t object have corresponding user preferences. For example, the prompt callback function is not stored in the user preferences since it has no meaning outside of the current application. Some options which are not currently stored in the preferences may be stored there in the future.
+If you are implementing a user interface for credentials acquisition, you should be aware that KIM has a user preference to manage the initial credential options preferences. If the user successfully acquires credentials with non-default options and kim_preferences_get_remember_options() is set to TRUE, you should store the options used to get credentials with kim_preferences_set_options().

+Client Identity Preferences

+KIM also provides user preferences for the default client identity. This identity is used whenever KIM needs to display a graphical dialog for credential acquisition but does not know what client identity to use. You can view and edit the default client identity using kim_preferences_get_client_identity() and kim_preferences_set_client_identity().

+If you are implementing a user interface for credentials acquisition, you should be aware that KIM has a user preference to manage the client identity preferences. If the user successfully acquires credentials with non-default options and kim_preferences_get_remember_client_identity() is set to TRUE, you should store the client identity for which credentials were acquired using kim_preferences_set_client_identity().

+Favorite Identities Preferences

+As Kerberos becomes more widespread, the number of possible Kerberos identities and realms a user might want to use will become very large. Sites may list hundreds of realms in their Kerberos configuration files. In addition, sites may wish to use DNS SRV records to avoid having to list all the realms they use in their Kerberos configuration. As a result, the list of realms in the Kerberos configuration may be exceedingly large and/or incomplete. Users may also use multiple identities from the same realm.

+On platforms which use a GUI to acquire credentials, the KIM would like to to display a list of identities for the user to select from. Depending on what is appropriate for the platform, identities may be displayed in a popup menu or other list.

+To solve this problem, the KIM maintains a list of favorite identities specifically for identity selection. This list is a set of unique identities in alphabetical order (as appropriate for the user's language localization).

+Each identity may optionally have its own options for ticket acquisition. This allows KIM UIs to remember what ticket options worked for a specific identity. For example if the user normally wants renewable tickets but they have one identity at a KDC which rejects requests for renewable tickets, the "not renewable" option can be associated with that identity without changing the user's default preference to get renewable tickets. If an identity should use the default options, just pass KIM_OPTIONS_DEFAULT.

+Most callers will not need to use the favorite identities APIs. However if you are implementing your own graphical prompt callback or a credential management application, you may to view and/or edit the user's favorite identities.

+Viewing and Editing the Favorite Identities

+First, you need to acquire the Favorite Identities stored in the user's preferences using kim_preferences_create().

+Then use kim_preferences_get_number_of_favorite_identities() and kim_preferences_get_favorite_identity_at_index() to display the identities list. Use kim_preferences_add_favorite_identity() and kim_preferences_remove_favorite_identity() to change which identities are in the identities list. Identities are always stored in alphabetical order and duplicate identities are not permitted, so when you add or remove a identity you should redisplay the entire list. If you wish to replace the identities list entirely, use kim_preferences_remove_all_favorite_identities() to clear the list before adding your identities.

+Once you are done editing the favorite identities list, store changes in the user's preference file using kim_preferences_synchronize().

+See KIM Preferences Documentation for information on specific APIs.


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_selection_hints_overview.html b/krb5-1-7/doc/kim/html/kim_selection_hints_overview.html new file mode 100644 index 000000000..44a1cd28d --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_selection_hints_overview.html @@ -0,0 +1,55 @@ + + +Kerberos Identity Management: KIM Selection Hints Overview + + + + +

KIM Selection Hints Overview

+Introduction

+Most users belong to multiple organizations and thus need to authenticate to multiple Kerberos realms. Traditionally Kerberos sites solved this problem by setting up a cross-realm relationship, which allowed the user to use TGT credentials for their client identity in one realm to obtain credentials in another realm via cross-realm authentication. As a result users could acquire credentials for a single client identity and use them everywhere.

+Setting up cross-realm requires that realms share a secret, so sites must coordinate with one another to set up a cross-realm relationship. In addition, sites must set up authorization policies for users from other realms. As Kerberos becomes increasingly wide-spread, many realms will not have cross-realm relationships, and users will need to manually obtain credentials for their client identity at each realm (eg: "user@BANK.COM", "user@UNIVERSITY.EDU", etc). As a result, users will often have multiple credentials caches, one for each client identity.

+Unfortunately this presents a problem for applications which need to obtain service credentials. Which client identity should they use? Rather than having each application to manually search the cache collection, KIM provides a selection hints API for choosing the best client identity. This API is intended to simplify the process of choosing credentials and provide consistent behavior across all applications.

+Searching the cache collection for credentials may be expensive if there are a large number of caches. If credentials for the client identity are expired or not present, KIM may also wish to prompt the user for new credentials for the appropriate client identity. As a result, applications might want to remember which client identity worked in the past and always request credentials using that identity.

+Creating KIM Selection Hints

+A KIM selection hints object consists of an application identifier and one or more pieces of information about the service the client application will be contacting. The application identifier is used by user preferences to control how applications share cache entries. It is important to be consistent about what application identifier you provide. Java-style identifiers are recommended to avoid collisions.

+Selection Hint Search Behavior

+When using selection hints to search for an appropriate client identity, KIM uses a consistent hint search order. This allows applications to specify potentially contradictory information without preventing KIM from locating a single ccache. In addition the selection hint search order may change, especially if more hints are added.

+As a result, callers are encouraged to provide all relevant search hints, even if only a subset of those search hints are necessary to get reasonable behavior in the current implementation. Doing so will provide the most user-friendly selection experience.

+Currently the search order looks like this:

+

    +
  • Service Identity The client identity which has obtained a service credential for this service identity.
  • +
  • Server A client identity which has obtained a service credential for this server.
  • +
  • Service Realm A client identity which has obtained a service credential for this realm.
  • +
  • Service A client identity which has obtained a service credential for this service.
  • +
  • Client Realm A client identity in this realm.
  • +
  • User A client identity whose first component is this user string.
  • +
+For example, if you specify a service identity and a credential for that identity already exists in the ccache collection, KIM may use that ccache, even if your user and client realm entries in the selection hints would lead it to choose a different ccache. If no credentials for the service identity exist then KIM will fall back on the user and realm hints.

+

Note:
Due to performance and information exposure concerns, currently all searching is done by examining the cache collection. In the future the KIM may also make network requests as part of its search algorithm. For example it might check to see if the TGT credentials in each ccache can obtain credentials for the service identity specified by the selection hints.
+

+Selecting an Identity Using Selection Hints

+Once you have provided search criteria for selecting an identity, use kim_selection_hints_get_identity() to obtain an identity object. You can then use kim_identity_get_string() to obtain a krb5 principal string for use with gss_import_name() and gss_acquire_cred(). Alternatively, you can use kim_ccache_create_from_client_identity() to obtain a ccache containing credentials for the identity.

+

Note:
kim_selection_hints_get_identity() obtains an identity based on the current state of the selection hints object. If you change the selection hints object you must call kim_selection_hints_get_identity() again.
+

+Selection Hint Caching Behavior

+In addition to using selection hints to search for an appropriate client identity, KIM can also use them to remember which client identity worked. KIM maintains a per-user cache mapping selection hints to identities so that applications do not have to maintain their own caches or present user interface for selecting which cache to use.

+When kim_selection_hints_get_identity() is called KIM looks up in the cache and returns the identity which the selection hints map to. If there is not a preexisting cache entry for the selection hints then kim_selection_hints_get_identity() will search for an identity and prompt the user if it cannot find an appropriate one.

+If the client identity returned by KIM authenticates and passes authorization checks, you should tell KIM to cache the identity by calling kim_selection_hints_remember_identity(). This will create a cache entry for the mapping between your selection hints and the identity so that subsequent calls to kim_selection_hints_get_identity() do not need to prompt the user.

+If the client identity returned by KIM fails to authenticate or fails authorization checks, you must call kim_selection_hints_forget_identity() to remove any mapping that already exists. After this function is called, future calls to kim_selection_hints_get_identity() will search for an identity again. You may also wish to call this function if the user changes your application preferences such that the identity might be invalidated.

+

Note:
It is very important that you call kim_selection_hints_forget_identity() if your application fails to successfully establish a connection with the server. Otherwise the user can get "stuck" using the same non-working identity if they chose the wrong one accidentally or if their identity information changes. Because only your application understands the authorization checksof the protocol it uses, KIM cannot tell whether or not the identity worked.
+If you wish to search and prompt for an identity without using the cached mappings, you can turn off the cached mapping lookups using kim_selection_hints_set_remember_identity(). This is not recommended for most applications since it will result in a lot of unnecessary searching and prompting for identities.

+

Note:
Because cache entries key off of selection hints, it is important to always specify the same hints when contacting a particular service. Otherwise KIM will not always find the cache entries.
+

+Selection Hint Prompting Behavior

+If valid credentials for identity in the selection hints cache are unavailable or if no identity could be found using searching or caching when kim_selection_hints_get_identity() is called, KIM may present a GUI to ask the user to select an identity or acquire credentials for an identity.

+

Note:
Because of the caching behavior described above the user will only be prompted to choose an identity when setting up the application or when their identity stops working.
+In order to let the user know why Kerberos needs their assistance, KIM displays the name of the application which requested the identity selection. Unfortunately, some platforms do not provide a runtime mechanism for determining the name of the calling process. If your application runs on one of these platforms (or is cross-platform) you should provide a localized version of its name with the private function kim_library_set_application_name().

+In many cases a single application may select different identities for different purposes. For example an email application might use different identities to check mail for different accounts. If your application has this property you may need to provide the user with a localized string describing how the identity will be used. You can specify this string with kim_selection_hints_get_explanation(). You can find out what string will be used with kim_selection_hints_set_explanation().

+Since the user may choose to acquire credentials when selection an identity, KIM also provides kim_selection_hints_set_options() to set what credential acquisition options are used. kim_selection_hints_get_options() returns the options which will be used.

+If you need to disable user interaction, use kim_selection_hints_set_allow_user_interaction(). Use kim_selection_hints_get_allow_user_interaction() to find out whether or not user interaction is enabled. User interaction is enabled by default.

+See KIM Selection Hints Reference Documentation for information on specific APIs.


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/kim_string_overview.html b/krb5-1-7/doc/kim/html/kim_string_overview.html new file mode 100644 index 000000000..fbc0962ac --- /dev/null +++ b/krb5-1-7/doc/kim/html/kim_string_overview.html @@ -0,0 +1,18 @@ + + +Kerberos Identity Management: KIM String Overview + + + + +

KIM String Overview

A UTF8 string.

+Memory management routines are provided for runtime consistency on operating systems with shared libraries and multiple runtimes.

+KIM Error Messages

+Like most C APIs, the KIM API returns numeric error codes. These error codes may come from KIM, krb5 or GSS APIs. In most cases the caller will want to handle these error programmatically. However, in some circumstances the caller may wish to print an error string to the user.

+One problem with just printing the error code to the user is that frequently the context behind the error has been lost. For example if KIM is trying to obtain credentials via referrals, it may fail partway through the process. In this case the error code will be KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, which maps to "Client not found in Kerberos database". Unfortunately this error isn't terribly helpful because it doesn't tell the user whether they typoed their principal name or if referrals failed.

+To avoid this problem, KIM maintains an explanatory string for the last error seen in each thread calling into KIM. If a caller wishes to display an error to the user, immediately after getting the error the caller should call kim_string_create_for_last_error() to obtain a copy of the descriptive error message.

+See KIM String Reference Documentation for information on specific APIs.


Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/modules.html b/krb5-1-7/doc/kim/html/modules.html new file mode 100644 index 000000000..0239b81d5 --- /dev/null +++ b/krb5-1-7/doc/kim/html/modules.html @@ -0,0 +1,25 @@ + + +Kerberos Identity Management: Module Index + + + + +

Kerberos Identity Management Modules

Here is a list of all modules: +
Generated on Mon Nov 3 17:45:44 2008 for Kerberos Identity Management by  + +doxygen 1.5.3
+ + diff --git a/krb5-1-7/doc/kim/html/tab_b.gif b/krb5-1-7/doc/kim/html/tab_b.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d623483ffdf5f9f96900108042a7ab0643fe2a3 GIT binary patch literal 35 ncmZ?wbhEHbWMp7uXkcJy*>IeJfk6j|fqX^=1|}vKMh0sDa2W*H literal 0 HcmV?d00001 diff --git a/krb5-1-7/doc/kim/html/tab_l.gif b/krb5-1-7/doc/kim/html/tab_l.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b1e6337c9299a700401a2a78a2c6ffced475216 GIT binary patch literal 706 zcmZ?wbhEHbZT`}F1e&(Gg}Y(8=I;HA5#Z$3JI=gGB)FQ#odI(O&E^@q;x zK6mr*m3xOS-#u~t!I@i+u0DKm^U160k6t`|^WpV}&n+8{U%dD9&a>B#U%!9-@yol< zU%&tQ{rk_K|NsC0`}dE5ET99@1@a36+kb~?0UJ*yc&I3X_m z!ND^5$O7$#8OFRuDhG}!?8z?cdZK&!`PWjdR;Aj^wZ` zeK{IEYHBJ)6K8VIp1`BVt++swf6j+=L{p1*nO(VhE`pFexG@5$|>uaCcd z`0m=9m+yak{QmXN#Sc$^{$X9h9&q2jiKAI|&T)a;PPx2K9p`YIdw8HtR5k2Q$2-O2 z*;3y{MQ-RnJTgJfI&R5|O)AHxDf_00XbPvDZPy4t=hHd)nfLPvms&O`Ok(sD()5v$ z5U@&h;a=#xbxVbo2~X&Xj0Ie(f{v>vERH+qC+nTG=B8Nca=wU-O$?1&vUgV~9=!H; zx>3p9Yn%*<>t~sk+&0xfyS8RsPfYBd<~wWK%j-LmpU>O7yX^h#UCp1x-p#i7@bE;py8XI6 zmY<)m>~)W~yIWcMVoiPg{duuf<*)9qZ9l$m*Ph&W&$jlv*Vpa+{pH@n=IQ$L?0$ax ec60Ul|8o2P|NVbd{6P)#weSbE3}s?04AuZvx_~SI literal 0 HcmV?d00001 diff --git a/krb5-1-7/doc/kim/html/tab_r.gif b/krb5-1-7/doc/kim/html/tab_r.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce9dd9f533cb5486d6941844f442b59d4a9e9175 GIT binary patch literal 2585 zcmbV}`9Bkk1ILFF--w5zJc=ZZT(zjE=;2|_S)Qm~rCWz1Pc)KPl;jv%A#&v2*x}yc zmf2~Jm~&=xjJY?PqwIN}f8qQ2{r$uH{c*nJbmr{cR5??*egHrs-B=MzCF`3%e{FAW z{oL5xTHn~5TM{jaB;@|_Ue5F&Zb@p(kMyG{*;gWDg zyeL|eZf7Qd8=#bXzSiR{yzRgLSj-fJS8>lBjVHN z^o-0eS=nE6a`W;LChBs=`+QAJP~{b93>H^eRb5kCSC1zUNezun%`L5M?RDzv#%jk7 zYVRX=vATPD`+oEfum^{RM@GjuP?-r=yh0!p;Vx^T9G7~`7%5ydH%70=jyJ;;`d;hv92x3R=z{xp+Lg2!*@OK*K15-t&okoPtSED)h&$RLxdbA zseWm^C3d%-yRNi-ryk^!ek+C`n&~cd$#ZWct_cUL{l~i+Nzx^5d!n94(>bW-iL~Rl z&8r)?q|1DIo=0=judQ{FaGcfLERz8gfn3-Qt<2lksh{mzpT}DXxUuR^z=^key&q4! z+wWI45vL0k$R^(F#{qfqhUsN@WA+w-V?LPH33!Q?WFSB3)WBojE@hK41Nb?KfS+Qo zXgrzfsP$wr4Qzy*{OD>uJBjdgGM@VMml5)2f~_}lD*YyOb}Hjeobhz#4c`w(l^>KK zr?Ud;W~Z}*w;%hZ|2^p^+f06gJDJQD zeIhGADbDmm&6arh(q>EZ<7mjzg7l|z$hRL8=1>)Nv=S7CY$B}iYJ&*T_-T_OG*L1q ztZ3Lana33?y3AKnyq^YCF|4x%Rb5WU&2qcl{TFKey%QJeMxn^SdT!hZ5+0i1zeusiYVp-phBl7b5+Px-X&LhByq z0F&<;K0l2+v>qiHlXb#$jXMv$uK-dEGE9L~qtdU(XeRXmvu*K2Q&6!fD**JxYP4b4BR7FdJ$Qx9G9`J%-_X!a#LGpp3g9)VWytGCa;7`S1_e8F~!R+aSJ zOF17p2`H?2kPs8Q`_;U}+D%3p zs2-0BTqFwpUoBk`?P;iPQ(IbEA|JmMx!P&YYG|R@S=5Mnw;-?A6rEEVyV%d7{iU4a zNk`i!%F(Ykpm`}#oH;BjY->@b8vQedv;pza2FL&*6ufjd+*3Ute&>kes~TU?^KkojsTh(o~(3tk1Y6>4(yn( z#U*ID9@eg-beKo1B;HXe+}{Z%n@7m0+yxivuqk9~;!1LGQlah)xYK4>wgL}l6dsaN zIxlRlq`*`j9PG4*0hD6YV_b_2w5b#)o7J?`q#{GjvvKlD`T*dWcZx<-s(ZvLB44E# z=!|sw!?)@%y$oRNL#25WS3lzdii}TuQ3?CLnvQ1_n};2sT_;Y;#d3=+-(O% zMN$>O!3;ke(UuLR%h_&)N zs^!-@A>QR}4yB1bPp`9S19ikTbZ~O{&FF-yHK{En;mmShDUIEw03`j(DBIsM}Rjki2J#SQa3gFZTKBPDeIiLt9Z z%bL3(B@Qw%(B`wSMS~dPh$=R`(}lBoFXKy(s|*{#ru$wjsBc_O#zxNk9w+UUHmx(U zmJ8+M+ndtnZ<7|VU9Mbt61zpo9T&3%Wx&XII=#QJxjR`CZf22ac3d51Z?GD%LEe_&*t46Qf;4`bZ7p2K(Ab5>GfT^}4! zBT&HZD`^PEgWoI&{~o-ID0F?O`75sm(87x%A{(}Ch1)QlzdJ)1B-eqe5a(weg0`4lQIf1evjvbBY50DVbzO7CLf|vP z2#0(U-|jZ`H{y5N^o7%iK6H>_HEGN->U6^!)1{XpJV!!4(Ig7wzZQ*9WYF4X1rG0x z=1uA@i`rIAciubDC{;~b(|&|A@xkjRP5aRcvRU9tvIm}jDB6J eQ0-6-y)mpwdT=ayS0tBxKDA*~;EWmo literal 0 HcmV?d00001 diff --git a/krb5-1-7/doc/kim/html/tabs.css b/krb5-1-7/doc/kim/html/tabs.css new file mode 100644 index 000000000..c37faafe8 --- /dev/null +++ b/krb5-1-7/doc/kim/html/tabs.css @@ -0,0 +1,102 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs INPUT +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI.current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI.current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.nav +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; +} diff --git a/krb5-1-7/doc/krb5-protocol/draft-ietf-cat-kerberos-pk-init-09.txt b/krb5-1-7/doc/krb5-protocol/draft-ietf-cat-kerberos-pk-init-09.txt new file mode 100644 index 000000000..748f08954 --- /dev/null +++ b/krb5-1-7/doc/krb5-protocol/draft-ietf-cat-kerberos-pk-init-09.txt @@ -0,0 +1,908 @@ +INTERNET-DRAFT Brian Tung +draft-ietf-cat-kerberos-pk-init-09.txt Clifford Neuman +Updates: RFC 1510 ISI +expires December 1, 1999 Matthew Hur + CyberSafe Corporation + Ari Medvinsky + Excite + Sasha Medvinsky + General Instrument + John Wray + Iris Associates, Inc. + Jonathan Trostle + Cisco + + Public Key Cryptography for Initial Authentication in Kerberos + +0. Status Of This Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC 2026. 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. + + 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). + + The distribution of this memo is unlimited. It is filed as + draft-ietf-cat-kerberos-pk-init-09.txt, and expires December 1, + 1999. Please send comments to the authors. + +1. Abstract + + This document defines extensions (PKINIT) to the Kerberos protocol + specification (RFC 1510 [1]) to provide a method for using public + key cryptography during initial authentication. The methods + defined specify the ways in which preauthentication data fields and + error data fields in Kerberos messages are to be used to transport + public key data. + +2. Introduction + + The popularity of public key cryptography has produced a desire for + its support in Kerberos [2]. The advantages provided by public key + cryptography include simplified key management (from the Kerberos + perspective) and the ability to leverage existing and developing + public key certification infrastructures. + + Public key cryptography can be integrated into Kerberos in a number + of ways. One is to associate a key pair with each realm, which can + then be used to facilitate cross-realm authentication; this is the + topic of another draft proposal. Another way is to allow users with + public key certificates to use them in initial authentication. This + is the concern of the current document. + + PKINIT utilizes Diffie-Hellman keys in combination with digital + signature keys as the primary, required mechanism. It also allows + for the use of RSA keys. Note that PKINIT supports the use of + separate signature and encryption keys. + + PKINIT enables access to Kerberos-secured services based on initial + authentication utilizing public key cryptography. PKINIT utilizes + standard public key signature and encryption data formats within the + standard Kerberos messages. The basic mechanism is as follows: The + user sends a request to the KDC as before, except that if that user + is to use public key cryptography in the initial authentication + step, his certificate and a signature accompany the initial request + in the preauthentication fields. Upon receipt of this request, the + KDC verifies the certificate and issues a ticket granting ticket + (TGT) as before, except that the encPart from the AS-REP message + carrying the TGT is now encrypted utilizing either a Diffie-Hellman + derived key or the user's public key. This message is authenticated + utilizing the public key signature of the KDC. + + The PKINIT specification may also be used as a building block for + other specifications. PKCROSS [3] utilizes PKINIT for establishing + the inter-realm key and associated inter-realm policy to be applied + in issuing cross realm service tickets. As specified in [4], + anonymous Kerberos tickets can be issued by applying a NULL + signature in combination with Diffie-Hellman in the PKINIT exchange. + Additionally, the PKINIT specification may be used for direct peer + to peer authentication without contacting a central KDC. This + application of PKINIT is described in PKTAPP [5] and is based on + concepts introduced in [6, 7]. For direct client-to-server + authentication, the client uses PKINIT to authenticate to the end + server (instead of a central KDC), which then issues a ticket for + itself. This approach has an advantage over TLS [8] in that the + server does not need to save state (cache session keys). + Furthermore, an additional benefit is that Kerberos tickets can + facilitate delegation (see [9]). + +3. Proposed Extensions + + This section describes extensions to RFC 1510 for supporting the + use of public key cryptography in the initial request for a ticket + granting ticket (TGT). + + In summary, the following change to RFC 1510 is proposed: + + * Users may authenticate using either a public key pair or a + conventional (symmetric) key. If public key cryptography is + used, public key data is transported in preauthentication + data fields to help establish identity. The user presents + a public key certificate and obtains an ordinary TGT that may + be used for subsequent authentication, with such + authentication using only conventional cryptography. + + Section 3.1 provides definitions to help specify message formats. + Section 3.2 describes the extensions for the initial authentication + method. + +3.1. Definitions + + The extensions involve new preauthentication fields; we introduce + the following preauthentication types: + + PA-PK-AS-REQ 14 + PA-PK-AS-REP 15 + + The extensions also involve new error types; we introduce the + following types: + + KDC_ERR_CLIENT_NOT_TRUSTED 62 + KDC_ERR_KDC_NOT_TRUSTED 63 + KDC_ERR_INVALID_SIG 64 + KDC_ERR_KEY_TOO_WEAK 65 + KDC_ERR_CERTIFICATE_MISMATCH 66 + KDC_ERR_CANT_VERIFY_CERTIFICATE 70 + KDC_ERR_INVALID_CERTIFICATE 71 + KDC_ERR_REVOKED_CERTIFICATE 72 + KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 + KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74 + KDC_ERR_CLIENT_NAME_MISMATCH 75 + KDC_ERR_KDC_NAME_MISMATCH 76 + + We utilize the following typed data for errors: + + TD-PKINIT-CMS-CERTIFICATES 101 + TD-KRB-PRINCIPAL 102 + TD-KRB-REALM 103 + TD-TRUSTED-CERTIFIERS 104 + TD-CERTIFICATE-INDEX 105 + + We utilize the following encryption types (which map directly to + OIDs): + + dsaWithSHA1-CmsOID 9 + md5WithRSAEncryption-CmsOID 10 + sha1WithRSAEncryption-CmsOID 11 + rc2CBC-EnvOID 12 + rsaEncryption-EnvOID (PKCS#1 v1.5) 13 + rsaES-OAEP-ENV-OID (PKCS#1 v2.0) 14 + des-ede3-cbc-Env-OID 15 + + These mappings are provided so that a client may send the + appropriate enctypes in the AS-REQ message in order to indicate + support for the corresponding OIDs (for performing PKINIT). + + In many cases, PKINIT requires the encoding of an X.500 name as a + Realm. In these cases, the realm will be represented using a + different style, specified in RFC 1510 with the following example: + + NAMETYPE:rest/of.name=without-restrictions + + For a realm derived from an X.500 name, NAMETYPE will have the value + X500-RFC2253. The full realm name will appear as follows: + + X500-RFC2253:RFC2253Encode(DistinguishedName) + + where DistinguishedName is an X.500 name, and RFC2253Encode is a + readable UTF encoding of an X.500 name, as defined by + RFC 2253 [14] (part of LDAPv3). + + To ensure that this encoding is unique, we add the following rule + to those specified by RFC 2253: + + The order in which the attributes appear in the RFC 2253 + encoding must be the reverse of the order in the ASN.1 + encoding of the X.500 name that appears in the public key + certificate. The order of the relative distinguished names + (RDNs), as well as the order of the AttributeTypeAndValues + within each RDN, will be reversed. (This is despite the fact + that an RDN is defined as a SET of AttributeTypeAndValues, where + an order is normally not important.) + + Similarly, PKINIT may require the encoding of an X.500 name as a + PrincipalName. In these cases, the name-type of the principal name + shall be set to KRB_NT-X500-PRINCIPAL. This new name type is + defined as: + + KRB_NT_X500_PRINCIPAL 6 + + The name-string shall be set as follows: + + RFC2253Encode(DistinguishedName) + + as described above. + + RFC 1510 specifies the ASN.1 structure for PrincipalName as follows: + + PrincipalName ::= SEQUENCE { + name-type[0] INTEGER, + name-string[1] SEQUENCE OF GeneralString + } + + For the purposes of encoding an X.500 name within this structure, + the name-string shall be encoded as a single GeneralString. + + Note that name mapping may be required or optional based on + policy. + +3.1.1. Encryption and Key Formats + + In the exposition below, we use the terms public key and private + key generically. It should be understood that the term "public + key" may be used to refer to either a public encryption key or a + signature verification key, and that the term "private key" may be + used to refer to either a private decryption key or a signature + generation key. The fact that these are logically distinct does + not preclude the assignment of bitwise identical keys. + + In the case of Diffie-Hellman, the key shall be produced from the + agreed bit string as follows: + + * Truncate the bit string to the appropriate length. + * Rectify parity in each byte (if necessary) to obtain the key. + + For instance, in the case of a DES key, we take the first eight + bytes of the bit stream, and then adjust the least significant bit + of each byte to ensure that each byte has odd parity. + +3.1.2. Algorithm Identifiers + + PKINIT does not define, but does permit, the algorithm identifiers + listed below. + +3.1.2.1. Signature Algorithm Identifiers + + The following signature algorithm identifiers specified in [11] and + in [15] shall be used with PKINIT: + + id-dsa-with-sha1 (DSA with SHA1) + md5WithRSAEncryption (RSA with MD5) + sha-1WithRSAEncryption (RSA with SHA1) + +3.1.2.2 Diffie-Hellman Key Agreement Algorithm Identifier + + The following algorithm identifier shall be used within the + SubjectPublicKeyInfo data structure: dhpublicnumber + + This identifier and the associated algorithm parameters are + specified in RFC 2459 [15]. + +3.1.2.3. Algorithm Identifiers for RSA Encryption + + These algorithm identifiers are used inside the EnvelopedData data + structure, for encrypting the temporary key with a public key: + + rsaEncryption (RSA encryption, PKCS#1 v1.5) + id-RSAES-OAEP (RSA encryption, PKCS#1 v2.0) + + Both of the above RSA encryption schemes are specified in [16]. + Currently, only PKCS#1 v1.5 is specified by CMS [11], although the + CMS specification says that it will likely include PKCS#1 v2.0 in + the future. (PKCS#1 v2.0 addresses adaptive chosen ciphertext + vulnerability discovered in PKCS#1 v1.5.) + +3.1.2.4. Algorithm Identifiers for Encryption with Secret Keys + + These algorithm identifiers are used inside the EnvelopedData data + structure in the PKINIT Reply, for encrypting the reply key with the + temporary key: + des-ede3-cbc (3-key 3-DES, CBC mode) + rc2-cbc (RC2, CBC mode) + + The full definition of the above algorithm identifiers and their + corresponding parameters (an IV for block chaining) is provided in + the CMS specification [11]. + +3.2. Public Key Authentication + + Implementation of the changes in this section is REQUIRED for + compliance with PKINIT. + + It is assumed that all public keys are signed by some certification + authority (CA). The initial authentication request is sent as per + RFC 1510, except that a preauthentication field containing data + signed by the user's private key accompanies the request: + + PA-PK-AS-REQ ::= SEQUENCE { + -- PA TYPE 14 + signedAuthPack [0] SignedData + -- defined in CMS [11] + -- AuthPack (below) defines the data + -- that is signed + trustedCertifiers [1] SEQUENCE OF TrustedCas OPTIONAL, + -- CAs that the client trusts + kdcCert [2] IssuerAndSerialNumber OPTIONAL + -- as defined in CMS [11] + -- specifies a particular KDC + -- certificate if the client + -- already has it; + -- must be accompanied by + -- a single trustedCertifier + encryptionCert [3] IssuerAndSerialNumber OPTIONAL + -- For example, this may be the + -- client's Diffie-Hellman + -- certificate, or it may be the + -- client's RSA encryption + -- certificate. + } + + TrustedCas ::= CHOICE { + principalName [0] KerberosName, + -- as defined below + caName [1] Name + -- fully qualified X.500 name + -- as defined by X.509 + issuerAndSerial [2] IssuerAndSerialNumber OPTIONAL + -- Since a CA may have a number of + -- certificates, only one of which + -- a client trusts + } + + Usage of SignedData: + The SignedData data type is specified in the Cryptographic + Message Syntax, a product of the S/MIME working group of the IETF. + - The encapContentInfo field must contain the PKAuthenticator + and, optionally, the client's Diffie Hellman public value. + - The eContentType field shall contain the OID value for + id-data: iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs7(7) data(1) + - The eContent field is data of the type AuthPack (below). + - The signerInfos field contains the signature of AuthPack. + - The Certificates field, when non-empty, contains the client's + certificate chain. If present, the KDC uses the public key from + the client's certificate to verify the signature in the request. + Note that the client may pass different certificates that are used + for signing or for encrypting. Thus, the KDC may utilize a + different client certificate for signature verification than the + one it uses to encrypt the reply to the client. For example, the + client may place a Diffie-Hellman certificate in this field in + order to convey its static Diffie Hellman certificate to the KDC + enable static-ephemeral Diffie-Hellman mode for the reply. As + another example, the client may place an RSA encryption + certificate in this field. + + AuthPack ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL + -- if client is using Diffie-Hellman + } + + PKAuthenticator ::= SEQUENCE { + kdcName [0] PrincipalName, + kdcRealm [1] Realm, + cusec [2] INTEGER, + -- for replay prevention + ctime [3] KerberosTime, + -- for replay prevention + nonce [4] INTEGER + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + -- dhKeyAgreement + subjectPublicKey BIT STRING + -- for DH, equals + -- public exponent (INTEGER encoded + -- as payload of BIT STRING) + } -- as specified by the X.509 recommendation [10] + + AlgorithmIdentifier ::= SEQUENCE { + algorithm ALGORITHM.&id, + parameters ALGORITHM.&type + } -- as specified by the X.509 recommendation [10] + + If the client passes an issuer and serial number in the request, + the KDC is requested to use the referred-to certificate. If none + exists, then the KDC returns an error of type + KDC_ERR_CERTIFICATE_MISMATCH. It also returns this error if, on the + other hand, the client does not pass any trustedCertifiers, + believing that it has the KDC's certificate, but the KDC has more + than one certificate. The KDC should include information in the + KRB-ERROR message that indicates the KDC certificate(s) that a + client may utilize. This data is specified in the e-data, which + is defined in RFC 1510 revisions as a SEQUENCE of TypedData: + + TypedData ::= SEQUENCE { + data-type [0] INTEGER, + data-value [1] OCTET STRING, + } -- per Kerberos RFC 1510 revisions + + where: + data-type = TD-PKINIT-CMS-CERTIFICATES = 101 + data-value = CertificateSet // as specified by CMS [11] + + The PKAuthenticator carries information to foil replay attacks, + to bind the request and response. The PKAuthenticator is signed + with the private key corresponding to the public key in the + certificate found in userCert (or cached by the KDC). + + The trustedCertifiers field contains a list of certification + authorities trusted by the client, in the case that the client does + not possess the KDC's public key certificate. If the KDC has no + certificate signed by any of the trustedCertifiers, then it returns + an error of type KDC_ERR_KDC_NOT_TRUSTED. + + KDCs should try to (in order of preference): + 1. Use the KDC certificate identified by the serialNumber included + in the client's request. + 2. Use a certificate issued to the KDC by the client's CA (if in the + middle of a CA key roll-over, use the KDC cert issued under same + CA key as user cert used to verify request). + 3. Use a certificate issued to the KDC by one of the client's + trustedCertifier(s); + If the KDC is unable to comply with any of these options, then the + KDC returns an error message of type KDC_ERR_KDC_NOT_TRUSTED to the + client. + + Upon receipt of the AS_REQ with PA-PK-AS-REQ pre-authentication + type, the KDC attempts to verify the user's certificate chain + (userCert), if one is provided in the request. This is done by + verifying the certification path against the KDC's policy of + legitimate certifiers. This may be based on a certification + hierarchy, or it may be simply a list of recognized certifiers in a + system like PGP. + + If the client's certificate chain contains no certificate signed by + a CA trusted by the KDC, then the KDC sends back an error message + of type KDC_ERR_CANT_VERIFY_CERTIFICATE. The accompanying e-data + is a SEQUENCE of one TypedData (with type TD-TRUSTED-CERTIFIERS=104) + whose data-value is an OCTET STRING which is the DER encoding of + + TrustedCertifiers ::= SEQUENCE OF PrincipalName + -- X.500 name encoded as a principal name + -- see Section 3.1 + + If the signature on one of the certificates in the client's chain + fails verification, then the KDC returns an error of type + KDC_ERR_INVALID_CERTIFICATE. The accompanying e-data is a SEQUENCE + of one TypedData (with type TD-CERTIFICATE-INDEX=105) whose + data-value is an OCTET STRING which is the DER encoding of + + CertificateIndex ::= INTEGER + -- 0 = 1st certificate, + -- (in order of encoding) + -- 1 = 2nd certificate, etc + + The KDC may also check whether any of the certificates in the + client's chain has been revoked. If one of the certificates has + been revoked, then the KDC returns an error of type + KDC_ERR_REVOKED_CERTIFICATE; if such a query reveals that the + certificate's revocation status is unknown, the KDC returns an + error of type KDC_ERR_REVOCATION_STATUS_UNKNOWN; if the revocation + status is unavailable, the KDC returns an error of type + KDC_ERR_REVOCATION_STATUS_UNAVAILABLE. In any of these three + cases, the affected certificate is identified by the accompanying + e-data, which contains a CertificateIndex as described for + KDC_ERR_INVALID_CERTIFICATE. + + If the certificate chain can be verified, but the name of the + client in the certificate does not match the client's name in the + request, then the KDC returns an error of type + KDC_ERR_CLIENT_NAME_MISMATCH. There is no accompanying e-data + field in this case. + + Finally, if the certificate chain is verified, but the KDC's name + or realm as given in the PKAuthenticator does not match the KDC's + actual principal name, then the KDC returns an error of type + KDC_ERR_KDC_NAME_MISMATCH. The accompanying e-data field is again + a SEQUENCE of one TypedData (with type TD-KRB-PRINCIPAL=102 or + TD-KRB-REALM=103 as appropriate) whose data-value is an OCTET + STRING whose data-value is the DER encoding of a PrincipalName or + Realm as defined in RFC 1510 revisions. + + Even if all succeeds, the KDC may--for policy reasons--decide not + to trust the client. In this case, the KDC returns an error message + of type KDC_ERR_CLIENT_NOT_TRUSTED. + + If a trust relationship exists, the KDC then verifies the client's + signature on AuthPack. If that fails, the KDC returns an error + message of type KDC_ERR_INVALID_SIG. Otherwise, the KDC uses the + timestamp (ctime and cusec) in the PKAuthenticator to assure that + the request is not a replay. The KDC also verifies that its name + is specified in the PKAuthenticator. + + If the clientPublicValue field is filled in, indicating that the + client wishes to use Diffie-Hellman key agreement, then the KDC + checks to see that the parameters satisfy its policy. If they do + not (e.g., the prime size is insufficient for the expected + encryption type), then the KDC sends back an error message of type + KDC_ERR_KEY_TOO_WEAK. Otherwise, it generates its own public and + private values for the response. + + The KDC also checks that the timestamp in the PKAuthenticator is + within the allowable window and that the principal name and realm + are correct. If the local (server) time and the client time in the + authenticator differ by more than the allowable clock skew, then the + KDC returns an error message of type KRB_AP_ERR_SKEW. + + Assuming no errors, the KDC replies as per RFC 1510, except as + follows. The user's name in the ticket is determined by the + following decision algorithm: + + 1. If the KDC has a mapping from the name in the certificate + to a Kerberos name, then use that name. + Else + 2. If the certificate contains a Kerberos name in an extension + field, and local KDC policy allows, then use that name. + Else + 3. Use the name as represented in the certificate, mapping + as necessary (e.g., as per RFC 2253 for X.500 names). In + this case the realm in the ticket shall be the name of the + certification authority that issued the user's certificate. + + The KDC encrypts the reply not with the user's long-term key, but + with a random key generated only for this particular response. This + random key is sealed in the preauthentication field: + + PA-PK-AS-REP ::= CHOICE { + -- PA TYPE 15 + dhSignedData [0] SignedData, + -- Defined in CMS and used only with + -- Diffie-Helman key exchange + -- This choice MUST be supported + -- by compliant implementations. + encKeyPack [1] EnvelopedData, + -- Defined in CMS + -- The temporary key is encrypted + -- using the client public key + -- key + -- SignedReplyKeyPack, encrypted + -- with the temporary key, is also + -- included. + } + + Usage of SignedData: + If the Diffie-Hellman option is used, dhSignedData in PA-PK-AS-REP + provides authenticated Diffie-Hellman parameters of the KDC. The + reply key used to encrypt part of the KDC reply message is derived + from the Diffie-Hellman exchange: + - Both the KDC and the client calculate a secret value (g^ab mod p), + where a is the client's private exponent and b is the KDC's + private exponent. + - Both the KDC and the client take the first N bits of this secret + value and convert it into a reply key. N depends on the reply key + type. + - If the reply key is DES, N=64 bits, where some of the bits are + replaced with parity bits, according to FIPS PUB 74. + - If the reply key is (3-key) 3-DES, N=192 bits, where some of the + bits are replaced with parity bits, according to FIPS PUB 74. + - The encapContentInfo field must contain the KdcDHKeyInfo as + defined below. + - The eContentType field shall contain the OID value for + id-data: iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs7(7) data(1) + - The certificates field must contain the certificates necessary + for the client to establish trust in the KDC's certificate + based on the list of trusted certifiers sent by the client in + the PA-PK-AS-REQ. This field may be empty if the client did + not send to the KDC a list of trusted certifiers (the + trustedCertifiers field was empty, meaning that the client + already possesses the KDC's certificate). + - The signerInfos field is a SET that must contain at least one + member, since it contains the actual signature. + + Usage of EnvelopedData: + The EnvelopedData data type is specified in the Cryptographic + Message Syntax, a product of the S/MIME working group of the IETF. + It contains an temporary key encrypted with the PKINIT + client's public key. It also contains a signed and encrypted + reply key. + - The originatorInfo field is not required, since that information + may be presented in the signedData structure that is encrypted + within the encryptedContentInfo field. + - The optional unprotectedAttrs field is not required for PKINIT. + - The recipientInfos field is a SET which must contain exactly one + member of the KeyTransRecipientInfo type for encryption + with an RSA public key. + - The encryptedKey field (in KeyTransRecipientInfo) contains + the temporary key which is encrypted with the PKINIT client's + public key. + - The encryptedContentInfo field contains the signed and encrypted + reply key. + - The contentType field shall contain the OID value for + id-signedData: iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs7(7) signedData(2) + - The encryptedContent field is encrypted data of the CMS type + signedData as specified below. + - The encapContentInfo field must contains the ReplyKeyPack. + - The eContentType field shall contain the OID value for + id-data: iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs7(7) data(1) + - The eContent field is data of the type ReplyKeyPack (below). + - The certificates field must contain the certificates necessary + for the client to establish trust in the KDC's certificate + based on the list of trusted certifiers sent by the client in + the PA-PK-AS-REQ. This field may be empty if the client did + not send to the KDC a list of trusted certifiers (the + trustedCertifiers field was empty, meaning that the client + already possesses the KDC's certificate). + - The signerInfos field is a SET that must contain at least one + member, since it contains the actual signature. + + KdcDHKeyInfo ::= SEQUENCE { + -- used only when utilizing Diffie-Hellman + nonce [0] INTEGER, + -- binds responce to the request + subjectPublicKey [2] BIT STRING + -- Equals public exponent (g^a mod p) + -- INTEGER encoded as payload of + -- BIT STRING + } + + ReplyKeyPack ::= SEQUENCE { + -- not used for Diffie-Hellman + replyKey [0] EncryptionKey, + -- used to encrypt main reply + -- ENCTYPE is at least as strong as + -- ENCTYPE of session key + nonce [1] INTEGER, + -- binds response to the request + -- must be same as the nonce + -- passed in the PKAuthenticator + } + + + Since each certifier in the certification path of a user's + certificate is essentially a separate realm, the name of each + certifier must be added to the transited field of the ticket. The + format of these realm names is defined in Section 3.1 of this + document. If applicable, the transit-policy-checked flag should be + set in the issued ticket. + + The KDC's certificate must bind the public key to a name derivable + from the name of the realm for that KDC. X.509 certificates shall + contain the principal name of the KDC as the SubjectAltName version + 3 extension. Below is the definition of this version 3 extension, as + specified by the X.509 standard: + + subjectAltName EXTENSION ::= { + SYNTAX GeneralNames + IDENTIFIED BY id-ce-subjectAltName + } + + GeneralNames ::= SEQUENCE SIZE(1..MAX) OF GeneralName + + GeneralName ::= CHOICE { + otherName [0] INSTANCE OF OTHER-NAME, + ... + } + + OTHER-NAME ::= TYPE-IDENTIFIER + + In this definition, otherName is a name of any form defined as an + instance of the OTHER-NAME information object class. For the purpose + of specifying a Kerberos principal name, INSTANCE OF OTHER-NAME will + be chosen and replaced by the type KerberosName: + + KerberosName ::= SEQUENCE { + realm [0] Realm, + -- as define in RFC 1510 + principalName [1] PrincipalName, + -- as define in RFC 1510 + } + + This specific syntax is identified within subjectAltName by setting + the OID id-ce-subjectAltName to krb5PrincipalName, where (from the + Kerberos specification) we have + + krb5 OBJECT IDENTIFIER ::= { iso (1) + org (3) + dod (6) + internet (1) + security (5) + kerberosv5 (2) } + + krb5PrincipalName OBJECT IDENTIFIER ::= { krb5 2 } + + This specification may also be used to specify a Kerberos name + within the user's certificate. + + If a non-KDC X.509 certificate contains the principal name within + the subjectAltName version 3 extension , that name may utilize + KerberosName as defined below, or, in the case of an S/MIME + certificate [17], may utilize the email address. If the KDC + is presented with as S/MIME certificate, then the email address + within subjectAltName will be interpreted as a principal and realm + separated by the "@" sign, or as a name that needs to be + canonicalized. If the resulting name does not correspond to a + registered principal name, then the principal name is formed as + defined in section 3.1. + + The client then extracts the random key used to encrypt the main + reply. This random key (in encPaReply) is encrypted with either the + client's public key or with a key derived from the DH values + exchanged between the client and the KDC. + +3.2.2. Required Algorithms + + Not all of the algorithms in the PKINIT protocol specification have + to be implemented in order to comply with the proposed standard. + Below is a list of the required algorithms: + + - Diffie-Hellman public/private key pairs + - utilizing Diffie-Hellman ephemeral-ephemeral mode + - SHA1 digest and DSA for signatures + - 3-key triple DES keys derived from the Diffie-Hellman Exchange + - 3-key triple DES Temporary and Reply keys + +4. Logistics and Policy + + This section describes a way to define the policy on the use of + PKINIT for each principal and request. + + The KDC is not required to contain a database record for users + who use public key authentication. However, if these users are + registered with the KDC, it is recommended that the database record + for these users be modified to an additional flag in the attributes + field to indicate that the user should authenticate using PKINIT. + If this flag is set and a request message does not contain the + PKINIT preauthentication field, then the KDC sends back as error of + type KDC_ERR_PREAUTH_REQUIRED indicating that a preauthentication + field of type PA-PK-AS-REQ must be included in the request. + +5. Security Considerations + + PKINIT raises a few security considerations, which we will address + in this section. + + First of all, PKINIT introduces a new trust model, where KDCs do not + (necessarily) certify the identity of those for whom they issue + tickets. PKINIT does allow KDCs to act as their own CAs, in order + to simplify key management, but one of the additional benefits is to + align Kerberos authentication with a global public key + infrastructure. Anyone using PKINIT in this way must be aware of + how the certification infrastructure they are linking to works. + + Secondly, PKINIT also introduces the possibility of interactions + between different cryptosystems, which may be of widely varying + strengths. Many systems, for instance, allow the use of 512-bit + public keys. Using such keys to wrap data encrypted under strong + conventional cryptosystems, such as triple-DES, is inappropriate; + it adds a weak link to a strong one at extra cost. Implementors + and administrators should take care to avoid such wasteful and + deceptive interactions. + + Lastly, PKINIT calls for randomly generated keys for conventional + cryptosystems. Many such systems contain systematically "weak" + keys. PKINIT implementations MUST avoid use of these keys, either + by discarding those keys when they are generated, or by fixing them + in some way (e.g., by XORing them with a given mask). These + precautions vary from system to system; it is not our intention to + give an explicit recipe for them here. + +6. Transport Issues + + Certificate chains can potentially grow quite large and span several + UDP packets; this in turn increases the probability that a Kerberos + message involving PKINIT extensions will be broken in transit. In + light of the possibility that the Kerberos specification will + require KDCs to accept requests using TCP as a transport mechanism, + we make the same recommendation with respect to the PKINIT + extensions as well. + +7. Bibliography + + [1] J. Kohl, C. Neuman. The Kerberos Network Authentication Service + (V5). Request for Comments 1510. + + [2] B.C. Neuman, Theodore Ts'o. Kerberos: An Authentication Service + for Computer Networks, IEEE Communications, 32(9):33-38. September + 1994. + + [3] B. Tung, T. Ryutov, C. Neuman, G. Tsudik, B. Sommerfeld, + A. Medvinsky, M. Hur. Public Key Cryptography for Cross-Realm + Authentication in Kerberos. + draft-ietf-cat-kerberos-pk-cross-04.txt + + [4] A. Medvinsky, J. Cargille, M. Hur. Anonymous Credentials in + Kerberos. + draft-ietf-cat-kerberos-anoncred-00.txt + + [5] A. Medvinsky, M. Hur, B. Clifford Neuman. Public Key Utilizing + Tickets for Application Servers (PKTAPP). + draft-ietf-cat-pktapp-00.txt + + [6] M. Sirbu, J. Chuang. Distributed Authentication in Kerberos + Using Public Key Cryptography. Symposium On Network and Distributed + System Security, 1997. + + [7] B. Cox, J.D. Tygar, M. Sirbu. NetBill Security and Transaction + Protocol. In Proceedings of the USENIX Workshop on Electronic + Commerce, July 1995. + + [8] T. Dierks, C. Allen. The TLS Protocol, Version 1.0 + Request for Comments 2246, January 1999. + + [9] B.C. Neuman, Proxy-Based Authorization and Accounting for + Distributed Systems. In Proceedings of the 13th International + Conference on Distributed Computing Systems, May 1993. + + [10] ITU-T (formerly CCITT) Information technology - Open Systems + Interconnection - The Directory: Authentication Framework + Recommendation X.509 ISO/IEC 9594-8 + + [11] R. Housley. Cryptographic Message Syntax. + draft-ietf-smime-cms-13.txt, April 1999. + + [12] PKCS #7: Cryptographic Message Syntax Standard, + An RSA Laboratories Technical Note Version 1.5 + Revised November 1, 1993 + + [13] R. Rivest, MIT Laboratory for Computer Science and RSA Data + Security, Inc. A Description of the RC2(r) Encryption Algorithm + March 1998. + Request for Comments 2268. + + [14] M. Wahl, S. Kille, T. Howes. Lightweight Directory Access + Protocol (v3): UTF-8 String Representation of Distinguished Names. + Request for Comments 2253. + + [15] R. Housley, W. Ford, W. Polk, D. Solo. Internet X.509 Public + Key Infrastructure, Certificate and CRL Profile, January 1999. + Request for Comments 2459. + + [16] B. Kaliski, J. Staddon. PKCS #1: RSA Cryptography + Specifications, October 1998. + Request for Comments 2437. + + [17] S. Dusse, P. Hoffman, B. Ramsdell, J. Weinstein. + S/MIME Version 2 Certificate Handling, March 1998. + Request for Comments 2312 + +8. Acknowledgements + + Some of the ideas on which this proposal is based arose during + discussions over several years between members of the SAAG, the IETF + CAT working group, and the PSRG, regarding integration of Kerberos + and SPX. Some ideas have also been drawn from the DASS system. + These changes are by no means endorsed by these groups. This is an + attempt to revive some of the goals of those groups, and this + proposal approaches those goals primarily from the Kerberos + perspective. Lastly, comments from groups working on similar ideas + in DCE have been invaluable. + +9. Expiration Date + + This draft expires December 1, 1999. + +10. Authors + + Brian Tung + Clifford Neuman + USC Information Sciences Institute + 4676 Admiralty Way Suite 1001 + Marina del Rey CA 90292-6695 + Phone: +1 310 822 1511 + E-mail: {brian, bcn}@isi.edu + + Matthew Hur + CyberSafe Corporation + 1605 NW Sammamish Road + Issaquah WA 98027-5378 + Phone: +1 425 391 6000 + E-mail: matt.hur@cybersafe.com + + Ari Medvinsky + Excite + 555 Broadway + Redwood City, CA 94063 + Phone +1 650 569 2119 + E-mail: amedvins@excitecorp.com + + Sasha Medvinsky + General Instrument + 6450 Sequence Drive + San Diego, CA 92121 + Phone +1 619 404 2825 + E-mail: smedvinsky@gi.com + + John Wray + Iris Associates, Inc. + 5 Technology Park Dr. + Westford, MA 01886 + E-mail: John_Wray@iris.com + + Jonathan Trostle + 170 W. Tasman Dr. + San Jose, CA 95134 + E-mail: jtrostle@cisco.com diff --git a/krb5-1-7/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt b/krb5-1-7/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt new file mode 100755 index 000000000..1304ae2bc --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/krb5.constants b/krb5-1-7/doc/krb5-protocol/krb5.constants new file mode 100644 index 000000000..e7cc5b80e --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/rfc3961.txt b/krb5-1-7/doc/krb5-protocol/rfc3961.txt new file mode 100644 index 000000000..0ac50b959 --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/rfc3962.txt b/krb5-1-7/doc/krb5-protocol/rfc3962.txt new file mode 100644 index 000000000..762beedbd --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/rfc4120.txt b/krb5-1-7/doc/krb5-protocol/rfc4120.txt new file mode 100644 index 000000000..e2816aff2 --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/rfc4121.txt b/krb5-1-7/doc/krb5-protocol/rfc4121.txt new file mode 100644 index 000000000..b4115143f --- /dev/null +++ b/krb5-1-7/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-7/doc/krb5-protocol/rfc4557.txt b/krb5-1-7/doc/krb5-protocol/rfc4557.txt new file mode 100644 index 000000000..fe9a8810d --- /dev/null +++ b/krb5-1-7/doc/krb5-protocol/rfc4557.txt @@ -0,0 +1,339 @@ + + + + + + +Network Working Group L. Zhu +Request for Comments: 4557 K. Jaganathan +Category: Standards Track Microsoft Corporation + N. Williams + Sun Microsystems + June 2006 + + + Online Certificate Status Protocol (OCSP) Support for + Public Key Cryptography for + Initial Authentication in Kerberos (PKINIT) + +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 (2006). + +Abstract + + This document defines a mechanism to enable in-band transmission of + Online Certificate Status Protocol (OCSP) responses in the Kerberos + network authentication protocol. These responses are used to verify + the validity of the certificates used in Public Key Cryptography for + Initial Authentication in Kerberos (PKINIT), which is the Kerberos + Version 5 extension that provides for the use of public key + cryptography. + +Table of Contents + + 1. Introduction ....................................................2 + 2. Conventions Used in This Document ...............................2 + 3. Message Definition ..............................................2 + 4. Security Considerations .........................................3 + 5. Acknowledgements ................................................4 + 6. References ......................................................4 + 6.1. Normative References .......................................4 + 6.2. Informative References .....................................4 + + + + + + + +Zhu, et al. Standards Track [Page 1] + +RFC 4557 OCSP Support for PKINIT June 2006 + + +1. Introduction + + Online Certificate Status Protocol (OCSP) [RFC2560] enables + applications to obtain timely information regarding the revocation + status of a certificate. Because OCSP responses are well bounded and + small in size, constrained clients may wish to use OCSP to check the + validity of the certificates for Kerberos Key Distribution Center + (KDC) in order to avoid transmission of large Certificate Revocation + Lists (CRLs) and therefore save bandwidth on constrained networks + [OCSP-PROFILE]. + + This document defines a pre-authentication type [RFC4120], where the + client and the KDC MAY piggyback OCSP responses for certificates used + in authentication exchanges, as defined in [RFC4556]. + + By using this OPTIONAL extension, PKINIT clients and the KDC can + maximize the reuse of cached OCSP responses. + +2. Conventions Used in This Document + + In this document, the key words "MUST", "MUST NOT", "REQUIRED", + "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", + and "OPTIONAL" are to be interpreted as described in [RFC2119]. + +3. Message Definition + + A pre-authentication type identifier is defined for this mechanism: + + PA-PK-OCSP-RESPONSE 18 + + The corresponding padata-value field [RFC4120] contains the DER [X60] + encoding of the following ASN.1 type: + + PKOcspData ::= SEQUENCE OF OcspResponse + -- If more than one OcspResponse is + -- included, the first OcspResponse + -- MUST contain the OCSP response + -- for the signer's certificate. + -- The signer refers to the client for + -- AS-REQ, and the KDC for the AS-REP, + -- respectively. + + OcspResponse ::= OCTET STRING + -- Contains a complete OCSP response, + -- as defined in [RFC2560]. + + The client MAY send OCSP responses for certificates used in PA-PK- + AS-REQ [RFC4556] via a PA-PK-OCSP-RESPONSE. + + + +Zhu, et al. Standards Track [Page 2] + +RFC 4557 OCSP Support for PKINIT June 2006 + + + The KDC that receives a PA-PK-OCSP-RESPONSE SHOULD send a PA-PK- + OCSP-RESPONSE containing OCSP responses for certificates used in the + KDC's PA-PK-AS-REP. The client can request a PA-PK-OCSP-RESPONSE by + using a PKOcspData containing an empty sequence. + + The KDC MAY send a PA-PK-OCSP-RESPONSE when it does not receive a + PA-PK-OCSP-RESPONSE from the client. + + The PA-PK-OCSP-RESPONSE sent by the KDC contains OCSP responses for + certificates used in PA-PK-AS-REP [RFC4556]. + + Note the lack of integrity protection for the empty or missing OCSP + response; lack of an expected OCSP response from the KDC for the + KDC's certificates SHOULD be treated as an error by the client, + unless it is configured otherwise. + + When using OCSP, the response is signed by the OCSP server, which is + trusted by the receiver. Depending on local policy, further + verification of the validity of the OCSP servers may be needed + + The client and the KDC SHOULD ignore invalid OCSP responses received + via this mechanism, and they MAY implement CRL processing logic as a + fall-back position, if the OCSP responses received via this mechanism + alone are not sufficient for the verification of certificate + validity. The client and/or the KDC MAY ignore a valid OCSP response + and perform its own revocation status verification independently. + +4. Security Considerations + + The pre-authentication data in this document do not actually + authenticate any principals, but are designed to be used in + conjunction with PKINIT. + + There is no binding between PA-PK-OCSP-RESPONSE pre-authentication + data and PKINIT pre-authentication data other than a given OCSP + response corresponding to a certificate used in a PKINIT pre- + authentication data element. Attacks involving removal or + replacement of PA-PK-OCSP-RESPONSE pre-authentication data elements + are, at worst, downgrade attacks, where a PKINIT client or KDC would + proceed without use of CRLs or OCSP for certificate validation, or + denial-of-service attacks, where a PKINIT client or KDC that cannot + validate the other's certificate without an accompanying OCSP + response might reject the AS exchange or might have to download very + large CRLs in order to continue. Kerberos V does not protect against + denial-of-service attacks; therefore, the denial-of-service aspect of + these attacks is acceptable. + + + + + +Zhu, et al. Standards Track [Page 3] + +RFC 4557 OCSP Support for PKINIT June 2006 + + + If a PKINIT client or KDC cannot validate certificates without the + aid of a valid PA-PK-OCSP-RESPONSE, then it SHOULD fail the AS + exchange, possibly according to local configuration. + +5. Acknowledgements + + This document was based on conversations among the authors, Jeffrey + Altman, Sam Hartman, Martin Rex, and other members of the Kerberos + working group. + +6. References + +6.1. Normative References + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC2560] Myers, M., Ankney, R., Malpani, A., Galperin, S., and + C. Adams, "X.509 Internet Public Key Infrastructure + Online Certificate Status Protocol - OCSP", RFC 2560, + June 1999. + + [RFC4120] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The + Kerberos Network Authentication Service (V5)", RFC + 4120, July 2005. + + [RFC4556] Zhu, L. and B. Tung, "Public Key Cryptography for + Initial Authentication in Kerberos (PKINIT)", RFC + 4556, June 2006. + + [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. + +6.2. Informative References + + [OCSP-PROFILE] Deacon, A. and R. Hurst, "Lightweight OCSP Profile for + High Volume Environments", Work in Progress, May 2006. + + + + + + + + + + + +Zhu, et al. Standards Track [Page 4] + +RFC 4557 OCSP Support for PKINIT June 2006 + + +Authors' Addresses + + Larry Zhu + Microsoft Corporation + One Microsoft Way + Redmond, WA 98052 + US + + EMail: lzhu@microsoft.com + + + Karthik Jaganathan + Microsoft Corporation + One Microsoft Way + Redmond, WA 98052 + US + + EMail: karthikj@microsoft.com + + + Nicolas Williams + Sun Microsystems + 5300 Riata Trace Ct + Austin, TX 78727 + US + + EMail: Nicolas.Williams@sun.com + + + + + + + + + + + + + + + + + + + + + + + + +Zhu, et al. Standards Track [Page 5] + +RFC 4557 OCSP Support for PKINIT June 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. + +Acknowledgement + + Funding for the RFC Editor function is provided by the IETF + Administrative Support Activity (IASA). + + + + + + + +Zhu, et al. Standards Track [Page 6] + diff --git a/krb5-1-7/doc/krb5conf.texinfo b/krb5-1-7/doc/krb5conf.texinfo new file mode 100644 index 000000000..09825524f --- /dev/null +++ b/krb5-1-7/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-7/doc/man2html b/krb5-1-7/doc/man2html new file mode 100755 index 000000000..ea45686b8 --- /dev/null +++ b/krb5-1-7/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-7/doc/man2html.M b/krb5-1-7/doc/man2html.M new file mode 100644 index 000000000..537d6073b --- /dev/null +++ b/krb5-1-7/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-7/doc/man2ps b/krb5-1-7/doc/man2ps
new file mode 100755
index 000000000..06240e07c
--- /dev/null
+++ b/krb5-1-7/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-7/doc/man2ps.M b/krb5-1-7/doc/man2ps.M
new file mode 100644
index 000000000..d9c79032b
--- /dev/null
+++ b/krb5-1-7/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-7/doc/procedures.txt b/krb5-1-7/doc/procedures.txt
new file mode 100644
index 000000000..dcc21319a
--- /dev/null
+++ b/krb5-1-7/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-7/doc/rpc/design.tex b/krb5-1-7/doc/rpc/design.tex
new file mode 100644
index 000000000..fbd60f914
--- /dev/null
+++ b/krb5-1-7/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-7/doc/salts.texinfo b/krb5-1-7/doc/salts.texinfo
new file mode 100644
index 000000000..3ed43db0e
--- /dev/null
+++ b/krb5-1-7/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-7/doc/send-pr.texinfo b/krb5-1-7/doc/send-pr.texinfo
new file mode 100644
index 000000000..e34ca935e
--- /dev/null
+++ b/krb5-1-7/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-7/doc/support-enc.texinfo b/krb5-1-7/doc/support-enc.texinfo
new file mode 100644
index 000000000..c359db6ea
--- /dev/null
+++ b/krb5-1-7/doc/support-enc.texinfo
@@ -0,0 +1,37 @@
+@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 (weak)
+@item des-cbc-md4 
+DES cbc mode with RSA-MD4 (weak)
+@item des-cbc-md5 
+DES cbc mode with RSA-MD5 (weak)
+@item des-cbc-raw
+DES cbc mode raw (weak)
+@item des3-cbc-raw
+Triple DES cbc mode raw (weak)
+@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 (weak)
+@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 (weak)
+@end table
diff --git a/krb5-1-7/doc/texinfo-suppl.tex b/krb5-1-7/doc/texinfo-suppl.tex
new file mode 100644
index 000000000..4a1c0cdac
--- /dev/null
+++ b/krb5-1-7/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-7/doc/texinfo.tex b/krb5-1-7/doc/texinfo.tex
new file mode 100644
index 000000000..dddd0140f
--- /dev/null
+++ b/krb5-1-7/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-7/doc/thread-safe.txt b/krb5-1-7/doc/thread-safe.txt
new file mode 100644
index 000000000..0996b329a
--- /dev/null
+++ b/krb5-1-7/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-7/doc/threads.txt b/krb5-1-7/doc/threads.txt
new file mode 100644
index 000000000..b161dafbc
--- /dev/null
+++ b/krb5-1-7/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-7/doc/user-guide.texinfo b/krb5-1-7/doc/user-guide.texinfo
new file mode 100644
index 000000000..56f1c61dd
--- /dev/null
+++ b/krb5-1-7/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-7/src/BADSYMS b/krb5-1-7/src/BADSYMS
new file mode 100644
index 000000000..35b2c7c8f
--- /dev/null
+++ b/krb5-1-7/src/BADSYMS
@@ -0,0 +1,281 @@
+./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/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-7/src/Makefile.in b/krb5-1-7/src/Makefile.in
new file mode 100644
index 000000000..9bacc37eb
--- /dev/null
+++ b/krb5-1-7/src/Makefile.in
@@ -0,0 +1,637 @@
+datadir=@datadir@
+
+thisconfigdir=.
+myfulldir=.
+mydir=.
+# Don't build sample by default, and definitely don't install them
+# for production use:
+#	plugins/locate/python
+#	plugins/preauth/wpse
+#	plugins/preauth/cksum_body
+#	plugins/authdata/greet
+SUBDIRS=util include lib kdc kadmin @ldap_plugin_dir@ slave clients \
+	plugins/kdb/db2 \
+	plugins/preauth/pkinit \
+	plugins/preauth/encrypted_challenge \
+	appl tests \
+	config-files gen-manpages
+BUILDTOP=$(REL)$(C)
+LOCALINCLUDES = -I$(srcdir) 
+
+SRCS =  
+HDRS = 
+
+# Why aren't these flags showing up in Windows builds?
+##DOS##CPPFLAGS=$(CPPFLAGS) -D_X86_=1  -DWIN32 -D_WIN32 -W3 -D_WINNT
+
+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 ccapi
+	cd ..\ccapi
+	cd
+	$(MAKE) -$(MFLAGS)
+
+	@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_AD_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
+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 \
+	ccapi\Makefile \
+	ccapi\lib\win\Makefile \
+	ccapi\server\win\Makefile \
+    ccapi\test\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 \
+	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\gssapi\Makefile lib\gssapi\generic\Makefile \
+	lib\gssapi\krb5\Makefile lib\gssapi\mechglue\Makefile \
+	lib\gssapi\spnego\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##ccapi\Makefile: ccapi\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##ccapi\lib\win\Makefile: ccapi\lib\win\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##ccapi\server\win\Makefile: ccapi\server\win\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##ccapi\test\Makefile: ccapi\test\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##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\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\krb5\Makefile: lib\gssapi\krb5\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 clean in appl\gss-sample
+	cd ..\appl\gss-sample
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean 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/* 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/gssapi/* lib/gssapi/generic/* lib/gssapi/krb5/* \
+	lib/gssapi/mechglue/* lib/gssapi/spnego/* \
+	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= \
+    ccapi/common/* ccapi/common/win/* ccapi/common/win/OldCC/* \
+    ccapi/lib/* ccapi/lib/win/* ccapi/lib/win/OldCC/* \
+    ccapi/server/* ccapi/server/win/* \
+    ccapi\test\* \
+    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 \
+	$(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
+
+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
+$(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
+$(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
+
+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) ccapi\lib\win\$(OUTPRE)ccapi.dll "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) ccapi\server\win\$(OUTPRE)ccapiserver.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\."
+
+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
+
+COV_BUILD=	cov-build
+COV_ANALYZE=	cov-analyze
+COV_COMMIT=	cov-commit-defects --product "$(COV_PRODUCT)" --user "$(COV_USER)" --target "$(COV_TARGET)" --description "$(COV_DESC)"
+COV_MAKE_LIB=	cov-make-library
+
+COV_PRODUCT=	krb5
+COV_USER=	admin
+COV_DATADIR=
+COV_TARGET=	$(host)
+COV_DESC=
+
+# Set to, e.g., "--all" or "--security".
+COV_ANALYSES=
+# Temporary directory, might as well put it in the build tree.
+COV_TEMPDIR=	cov-temp
+# Sources modeling some functions or macros confusing Prevent.
+COV_MODELS=\
+	$(SRCTOP)/util/coverity-models/threads.c
+
+# Depend on Makefiles to ensure that (in maintainer mode) the configure
+# scripts won't get rerun under cov-build.
+coverity prevent cov: Makefiles
+	$(COV_BUILD) --dir $(COV_TEMPDIR) $(MAKE) all
+	$(COV_ANALYZE) $(COV_ANALYSES) --dir $(COV_TEMPDIR)
+	if test "$(COV_DATADIR)" != ""; then \
+		$(COV_COMMIT) --dir $(COV_TEMPDIR) --datadir $(COV_DATADIR); \
+	else \
+		echo "** Coverity Prevent analysis results not commit to Defect Manager"; \
+	fi
diff --git a/krb5-1-7/src/aclocal.m4 b/krb5-1-7/src/aclocal.m4
new file mode 100644
index 000000000..caa2db388
--- /dev/null
+++ b/krb5-1-7/src/aclocal.m4
@@ -0,0 +1,1773 @@
+AC_PREREQ(2.52)
+AC_COPYRIGHT([Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+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
+KRB5_AC_CHOOSE_ET dnl
+KRB5_AC_CHOOSE_SS dnl
+KRB5_AC_CHOOSE_DB dnl
+dnl allow stuff in tree to access deprecated stuff for now
+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)
+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)
+libpriv_frag=$srcdir/$ac_config_fragdir/libpriv.in
+AC_SUBST_FILE(libpriv_frag)
+libnodeps_frag=$srcdir/$ac_config_fragdir/libnodeps.in
+AC_SUBST_FILE(libnodeps_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"
+      ;;
+    solaris2.[[1-9]])
+      # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't
+      # get the right result.   XXX What about Solaris 9 and earlier?
+      if test "$GCC" = yes ; then
+        PTHREAD_CFLAGS="-D_REENTRANT -pthreads"
+      fi
+      ;;
+    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
+      # On Solaris 10, the thread support is always available in libc.
+      AC_DEFINE(NO_WEAK_PTHREADS,1,[Define if references to pthread routines should be non-weak.])
+      ;;
+  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
+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
+])
+AC_DEFUN(KRB5_AC_CHECK_FOR_CFLAGS,[
+AC_BEFORE([$0],[AC_PROG_CC])
+AC_BEFORE([$0],[AC_PROG_CXX])
+krb5_ac_cflags_set=${CFLAGS+set}
+krb5_ac_cxxflags_set=${CXXFLAGS+set}
+krb5_ac_warn_cflags_set=${WARN_CFLAGS+set}
+krb5_ac_warn_cxxflags_set=${WARN_CXXFLAGS+set}
+])
+dnl
+AC_DEFUN(TRY_WARN_CC_FLAG,[dnl
+  cachevar=`echo "krb5_cv_cc_flag_$1" | sed s/[[^a-zA-Z0-9_]]/_/g`
+  AC_CACHE_CHECK([if C compiler supports $1], [$cachevar],
+  [# first try without, then with
+  AC_TRY_COMPILE([], 1;,
+    [old_cflags="$CFLAGS"
+     CFLAGS="$CFLAGS $1"
+     AC_TRY_COMPILE([], 1;, eval $cachevar=yes, eval $cachevar=no)
+     CFLAGS="$old_cflags"],
+    [AC_MSG_ERROR(compiling simple test program with $CFLAGS failed)])])
+  if eval test '"${'$cachevar'}"' = yes; then
+    WARN_CFLAGS="$WARN_CFLAGS $1"
+  fi
+  eval flag_supported='${'$cachevar'}'
+])dnl
+dnl
+AC_DEFUN(WITH_CC,[dnl
+AC_REQUIRE([KRB5_AC_CHECK_FOR_CFLAGS])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CXX])dnl
+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])
+AC_ARG_WITH([size-optimizations],
+[  --with-size-optimizations enable a few optimizations to reduce code size
+                          possibly at some run-time cost],
+,
+withval=no)
+if test "$withval" = yes; then
+  AC_DEFINE(CONFIG_SMALL,1,[Define to reduce code size even if it means more cpu usage])
+fi
+# -Wno-long-long, if needed, for k5-platform.h without inttypes.h etc.
+extra_gcc_warn_opts="-Wall -Wcast-qual -Wcast-align -Wshadow"
+# -Wmissing-prototypes
+if test "$GCC" = yes ; then
+  # Putting this here means we get -Os after -O2, which works.
+  if test "$with_size_optimizations" = yes && test "x$krb5_ac_cflags_set" != xset; then
+    AC_MSG_NOTICE(adding -Os optimization option)
+    case "$CFLAGS" in
+      "-g -O2") CFLAGS="-g -Os" ;;
+      "-O2")    CFLAGS="-Os" ;;
+      *)        CFLAGS="$CFLAGS -Os" ;;
+    esac
+  fi
+  if test "x$krb5_ac_warn_cflags_set" = xset ; then
+    AC_MSG_NOTICE(not adding extra gcc warning flags because WARN_CFLAGS was set)
+  else
+    AC_MSG_NOTICE(adding extra warning flags for gcc)
+    WARN_CFLAGS="$WARN_CFLAGS $extra_gcc_warn_opts -Wmissing-prototypes"
+    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
+      WARN_CFLAGS="$WARN_CFLAGS -pedantic"
+    fi
+    if test "$ac_cv_cxx_compiler_gnu" = yes; then
+      if test "x$krb5_ac_warn_cxxflags_set" = xset ; then
+        AC_MSG_NOTICE(not adding extra g++ warnings because WARN_CXXFLAGS was set)
+      else
+        AC_MSG_NOTICE(adding extra warning flags for g++)
+        WARN_CXXFLAGS="$WARN_CXXFLAGS $extra_gcc_warn_opts"
+      fi
+    fi
+    # Currently, G++ does not support -Wno-format-zero-length.
+    TRY_WARN_CC_FLAG(-Wno-format-zero-length)
+    # Other flags here may not be supported on some versions of
+    # gcc that people want to use.
+    for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof ; do
+      TRY_WARN_CC_FLAG(-W$flag)
+    done
+    #  old-style-definition? generates many, many warnings
+    #
+    # Warnings that we'd like to turn into errors on versions of gcc
+    # that support promoting only specific warnings to errors, but
+    # we'll take as warnings on older compilers.  (If such a warning
+    # is added after the -Werror=foo feature, you can just put
+    # error=foo in the above list, and skip the test for the
+    # warning-only form.)  At least in some versions, -Werror= doesn't
+    # seem to make the conditions actual errors, but still issues
+    # warnings; I guess we'll take what we can get.
+    #
+    # We're currently targeting C89+, not C99, so disallow some
+    # constructs.
+    for flag in declaration-after-statement variadic-macros ; do
+      TRY_WARN_CC_FLAG(-Werror=$flag)
+      if test "$flag_supported" = no; then
+        TRY_WARN_CC_FLAG(-W$flag)
+      fi
+    done
+    #  missing-prototypes? maybe someday
+    #
+  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
+  if test "`uname -s`" = SunOS ; then
+    # Using Solaris but not GCC, assume Sunsoft compiler.
+    # We have some error-out-on-warning options available.
+    # Sunsoft 12 compiler defaults to -xc99=all, it appears, so "inline"
+    # works, but it also means that declaration-in-code warnings won't
+    # be issued.
+    # -v -fd -errwarn=E_DECLARATION_IN_CODE ...
+    WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION -errwarn=E_BAD_PTR_INT_COMB_ARG -errwarn=E_PTR_TO_VOID_IN_ARITHMETIC"
+    WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64"
+  fi
+fi
+AC_SUBST(WARN_CFLAGS)
+AC_SUBST(WARN_CXXFLAGS)
+])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:$1/deps:$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:]DIR[/deps:$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,
+[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_RPATH_FLAGS)
+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(CXX_LINK)
+AC_SUBST(RPATH_FLAG)
+AC_SUBST(PROG_RPATH_FLAGS)
+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
+
+AC_ARG_ENABLE([static],,
+[if test "$enableval" != no; then
+  AC_MSG_ERROR([Sorry, static libraries do not work in this release.])
+fi])
+AC_ARG_ENABLE([shared], , 
+[if test "$enableval" != yes; then
+  AC_MSG_ERROR([Sorry, this release builds only shared libraries, cannot disable them.])
+fi])
+AC_ARG_ENABLE([rpath],
+AC_HELP_STRING([--disable-rpath],[suppress run path flags in link lines]),
+[enable_rpath=$enableval],
+[enable_rpath=yes])
+
+if test "x$enable_rpath" != xyes ; then
+	# Unset the rpath flag values set by shlib.conf
+	SHLIB_RPATH_FLAGS=
+	RPATH_FLAG=
+	PROG_RPATH_FLAGS=
+fi
+
+if test "$SHLIBEXT" = ".so-nobuild"; then
+   AC_MSG_ERROR([Shared libraries are not yet supported on this platform.])
+fi
+
+DEPLIBEXT=$SHLIBEXT
+
+if test "$krb5_force_static" = "yes"; then
+	LIBLIST='lib$(LIBBASE)$(STLIBEXT)'
+	LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)'
+	OBJLISTS=OBJS.ST
+	# This used to be install-static, but now we only follow this
+	# path for internal libraries we don't want installed, not for
+	# configure-time requests for installed static libraries.
+	LIBINSTLIST=
+#	CFLAGS="$CFLAGS -D_KDB5_STATIC_LINK"
+
+	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([using shared libraries])
+
+	# Clear some stuff in case of AIX, etc.
+	if test "$STLIBEXT" = "$SHLIBEXT" ; then
+		STLIBEXT=.a-nobuild
+	fi
+	case "$SHLIBSEXT" in
+	.so.s-nobuild)
+		SHLIB_HAVE_MINOR_VERS=no
+		LIBLIST='lib$(LIBBASE)$(SHLIBEXT)'
+		LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)'
+		LIBINSTLIST="install-shared"
+		;;
+	*)
+		SHLIB_HAVE_MINOR_VERS=yes
+		LIBLIST='lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT)'
+		LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)'
+		LIBINSTLIST="install-shlib-soname"
+		;;
+	esac
+	OBJLISTS="OBJS.SH"
+fi
+CC_LINK="$CC_LINK_SHARED"
+CXX_LINK="$CXX_LINK_SHARED"
+AC_SUBST(SHLIB_HAVE_MINOR_VERS)
+
+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])])
+
+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],
+[#undef $2
+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
+])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-7/src/appl/Makefile.in b/krb5-1-7/src/appl/Makefile.in
new file mode 100644
index 000000000..02a1c73c5
--- /dev/null
+++ b/krb5-1-7/src/appl/Makefile.in
@@ -0,0 +1,8 @@
+thisconfigdir=..
+myfulldir=appl
+mydir=appl
+BUILDTOP=$(REL)..
+
+SUBDIRS= sample simple user_user gss-sample \
+	libpty bsd gssftp telnet
+
diff --git a/krb5-1-7/src/appl/bsd/Makefile.in b/krb5-1-7/src/appl/bsd/Makefile.in
new file mode 100644
index 000000000..5ec3c950f
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/Makefile.in
@@ -0,0 +1,84 @@
+thisconfigdir=.
+myfulldir=appl/bsd
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SETENVSRC=@SETENVSRC@
+SETENVOBJ=@SETENVOBJ@
+
+LOGINLIBS=@LOGINLIBS@
+LIBOBJS=@LIBOBJS@
+KRSHDLIBS=@KRSHDLIBS@
+
+SRCS= $(srcdir)/krcp.c $(srcdir)/krlogin.c $(srcdir)/krsh.c $(srcdir)/kcmd.c \
+	$(srcdir)/forward.c $(srcdir)/login.c $(srcdir)/krshd.c \
+	$(srcdir)/krlogind.c
+OBJS= krcp.o krlogin.o krsh.o kcmd.o forward.o $(SETENVOBJ) login.o krshd.o \
+	krlogind.o $(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
+
+clean:: 
+	$(RM) rsh rcp rlogin kshd klogind login.krb5
+
+rsh: krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o rsh krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_LIBS)
+
+rcp: krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o rcp krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_LIBS)
+
+rlogin: krlogin.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o rlogin krlogin.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB5_BASE_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
+
+kshd: krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o kshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
+
+klogind: krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o klogind krlogind.o  kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_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) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o login.krb5 login.o $(SETENVOBJ) $(LIBOBJS) $(LOGINLIBS) $(PTY_LIB) $(KRB5_BASE_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
diff --git a/krb5-1-7/src/appl/bsd/configure.in b/krb5-1-7/src/appl/bsd/configure.in
new file mode 100644
index 000000000..330c87d51
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/configure.in
@@ -0,0 +1,159 @@
+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"
+	)
+	;;
+esac
+dnl
+KRSHDLIBS="$LOGINLIBS"
+dnl
+AC_SUBST(KRSHDLIBS)
+AC_SUBST(LOGINLIBS)
+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 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
+
+KRB5_AC_LIBUTIL
+KRB5_BUILD_PROGRAM
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-7/src/appl/bsd/defines.h b/krb5-1-7/src/appl/bsd/defines.h
new file mode 100644
index 000000000..d04182bb9
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/defines.h
@@ -0,0 +1,85 @@
+#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);
+
+#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"
diff --git a/krb5-1-7/src/appl/bsd/deps b/krb5-1-7/src/appl/bsd/deps
new file mode 100644
index 000000000..f86eafa86
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/deps
@@ -0,0 +1,78 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)krcp.$(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-buf.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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 \
+  defines.h krcp.c
+$(OUTPRE)krlogin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.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 defines.h krlogin.c \
+  rpaths.h
+$(OUTPRE)krsh.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.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 defines.h krsh.c
+$(OUTPRE)kcmd.$(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-buf.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/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 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-buf.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/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)login.$(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-buf.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h login.c loginpaths.h
+$(OUTPRE)krshd.$(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/fake-addrinfo.h $(SRCTOP)/include/k5-buf.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \
+  $(SRCTOP)/include/k5-int-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 defines.h krshd.c \
+  loginpaths.h
+$(OUTPRE)krlogind.$(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/fake-addrinfo.h $(SRCTOP)/include/k5-buf.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \
+  $(SRCTOP)/include/k5-int-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 defines.h krlogind.c
diff --git a/krb5-1-7/src/appl/bsd/forward.c b/krb5-1-7/src/appl/bsd/forward.c
new file mode 100644
index 000000000..1ac2a2a2e
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/forward.c
@@ -0,0 +1,76 @@
+/*
+ * 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"
+
+#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.
+     */
+  
+    snprintf(ccname, sizeof(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-7/src/appl/bsd/getdtablesize.c b/krb5-1-7/src/appl/bsd/getdtablesize.c
new file mode 100644
index 000000000..244616cc9
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/kcmd.c b/krb5-1-7/src/appl/bsd/kcmd.c
new file mode 100644
index 000000000..199056944
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/kcmd.c
@@ -0,0 +1,1034 @@
+/*
+ * 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 "k5-int.h"
+
+#include "defines.h"
+
+extern krb5_context bsd_context;
+
+
+#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);
+static int do_lencheck;
+
+#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;
+    }
+    snprintf(rport_buf, sizeof(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) snprintf(num, sizeof(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 (asprintf(&cksumbuf, "%u:%s%s", ntohs(rport), cmd, remuser) < 0) {
+	fprintf(stderr, "Unable to allocate memory for checksum buffer.\n");
+	return(-1);
+    }
+    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_set_req_cksumtype(bsd_context, auth_context, CKSUMTYPE_RSA_MD5) !=0 )
+	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);
+}
+
+
+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();
+    }
+
+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;
+    }
+
+    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);
+}
+
+
+#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 = strdup(sp)) == NULL) {
+	fprintf(stderr, "no memory for saving args\n");
+	exit(1);
+    }
+    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;
+    int retval;
+    
+    if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
+	return 0;
+    }
+
+    if (!data_eq_string(*krb5_princ_realm(bsd_context, principal),
+			def_realm)) {
+	free(def_realm);
+	return 0;
+    }	
+    free(def_realm);
+    return 1;
+}
diff --git a/krb5-1-7/src/appl/bsd/klogind.M b/krb5-1-7/src/appl/bsd/klogind.M
new file mode 100644
index 000000000..574ae67b1
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/klogind.M
@@ -0,0 +1,174 @@
+.\" 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 \-rcpPef
+]
+[[ \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.
+.PP
+klogind allows Kerberos V5 authentication with the \fI.k5login\fP
+access control file to be trusted.  If this 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.
+.PP 
+The configuration of \fIklogind\fP is done
+by command line arguments passed by inetd.  The options are:
+
+.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.  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-7/src/appl/bsd/krcp.c b/krb5-1-7/src/appl/bsd/krcp.c
new file mode 100644
index 000000000..07a747b10
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/krcp.c
@@ -0,0 +1,1362 @@
+/*
+ *	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
+#include <stdarg.h>
+#include <sys/wait.h>
+
+#ifdef KERBEROS
+#include "k5-int.h"
+#include <k5-util.h>
+#include <com_err.h>
+
+#include "defines.h"
+
+#define RCP_BUFSIZ 4096
+     
+int sock;
+char *krb_realm = NULL;
+char *krb_cache = NULL;
+char *krb_config = NULL;
+krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
+krb5_context bsd_context;
+
+void	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;
+    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 = strdup(*argv))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    goto next_arg;
+	  case 'c':		/* Change default ccache file */
+	    argc--, argv++;
+	    if (argc == 0) 
+	      usage();
+	    if(!(krb_cache = strdup(*argv))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    goto next_arg;
+	  case 'C':		/* Change default config file */
+	    argc--, argv++;
+	    if (argc == 0) 
+	      usage();
+	    if(!(krb_config = strdup(*argv))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    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 (asprintf(&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 : "") < 0) {
+	fprintf(stderr, "rcp: Cannot malloc.\n");
+	exit(1);
+    }
+
+#else /* !KERBEROS */
+    (void) snprintf(cmd, sizeof(cmdbuf), "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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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 # */
+				  (struct sockaddr_in *) 0,
+				  (struct sockaddr_in *) 0,
+				  &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);
+			try_normal(orig_argv);
+		    }
+		    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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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,
+			      (struct sockaddr_in *) 0,
+			      &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);
+			try_normal(orig_argv);
+		} 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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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) snprintf(nambuf, sizeof(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) vsnprintf(cp, sizeof(buf) - (cp - buf), 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;
+
+#endif /* KERBEROS */
diff --git a/krb5-1-7/src/appl/bsd/krlogin.c b/krb5-1-7/src/appl/bsd/krlogin.c
new file mode 100644
index 000000000..98b61ac2b
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/krlogin.c
@@ -0,0 +1,1808 @@
+/*
+ *    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>
+#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;
+
+#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;
+#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 = strdup(*argv))){
+	    fprintf(stderr, "rlogin: Cannot malloc.\n");
+	    exit(1);
+	}
+	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;
+    }
+#endif /* KERBEROS */
+    if (host == 0)
+      goto usage;
+    if (argc > 0)
+      goto usage;
+    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.  */
+			snprintf (term + strlen (term),
+				  sizeof(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;
+
+    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);
+	try_normal(orig_argv);
+    } 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");
+    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, x, f, F, c, PO, or PN\n");
+#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)
+      strlcpy (hostname, "???", sizeof(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, "%s", 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-7/src/appl/bsd/krlogind.c b/krb5-1-7/src/appl/bsd/krlogind.c
new file mode 100644
index 000000000..a097d33f0
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/krlogind.c
@@ -0,0 +1,1430 @@
+/*
+ *	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 krb5
+ * -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. 
+ *   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 "k5-int.h"
+#include <libpty.h>
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#include <k5-util.h>
+#endif
+
+int non_privileged = 0; /* set when connection is seen to be from */
+			/* a non-privileged port */
+
+#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	"k5ciepPD: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 *);
+
+int do_encrypt = 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':
+	break;
+	
+      case '5':
+	break;
+      case 'c':
+	checksum_required = 1;
+	break;
+      case 'i':
+	checksum_ignored = 1;
+	break;
+	
+#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':
+	  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 (fd < 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 (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 ...
+	 */
+	snprintf(buferror, sizeof(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){
+	    snprintf(buferror, sizeof(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 ...
+	 */
+	snprintf(buferror, sizeof(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) snprintf(buf + 1, sizeof(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) snprintf(buf, sizeof(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. */
+    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*/
+    
+    /* krb5_kuserok returns 1 if OK */
+    if (!client || !krb5_kuserok(bsd_context, client, lusername)) {
+	if (asprintf(&msg_fail,
+		      "User %s is not authorized to login to account %s",
+		      krusername, lusername) >= 0)
+	    fatal(netf, msg_fail);
+	else
+	    fatal(netf,
+		  "User is not authorized to login to specified account");
+    }
+
+    if (checksum_required && !valid_checksum) {
+	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.");
+    }
+}
+
+#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 [-ePf] [-D port] [-w[ip|maxhostlen[,[no]striplocal]]] or [r/R][k/K][x/e][p/P]logind");
+#else
+    syslog(LOG_ERR, 
+	   "usage: rlogind [-rPf] [-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;
+    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);
+    }
+
+    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;
+    }
+
+    status = krb5_recvauth_version(bsd_context, &auth_context, &netf,
+				   NULL, 0, keytab, &ticket, &version);
+    if (status) {
+	/*
+	 * 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 (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;
+
+    if (!(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);
+	krb5_data chksumbuf;
+	krb5_boolean valid = 0;
+
+	chksumbuf.data = NULL;
+	if (getsockname(netf, (struct sockaddr *) &adr, &adr_length) != 0)
+	    goto error_cleanup;
+	if (asprintf(&chksumbuf.data, "%u:%s%s", ntohs(adr.sin_port), term, lusername) < 0)
+	    goto error_cleanup;
+
+	chksumbuf.length = strlen(chksumbuf.data);
+	status = krb5_c_verify_checksum(bsd_context,
+					ticket->enc_part2->session,
+					KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+					&chksumbuf, authenticator->checksum,
+					&valid);
+	if (status == 0 && !valid) status = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+    error_cleanup:
+	if (chksumbuf.data)
+	    free(chksumbuf.data);
+	if (status) {
+	  krb5_free_authenticator(bsd_context, authenticator);
+	  return status;
+	}
+	*valid_checksum = 1;
+      }
+      krb5_free_authenticator(bsd_context, authenticator);
+    }
+
+    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-7/src/appl/bsd/krsh.c b/krb5-1-7/src/appl/bsd/krsh.c
new file mode 100644
index 000000000..1999bb5e1
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/krsh.c
@@ -0,0 +1,595 @@
+/*
+ *	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>
+#include "defines.h"
+#endif /* KERBEROS */
+
+/*
+ * 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;
+
+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, **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;
+#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 = strdup(*argv))){
+	    fprintf(stderr, "rsh(kerberos): Cannot malloc.\n");
+	    exit(1);
+	}
+	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;
+    args = (char *) malloc((unsigned) cc);
+    *args = '\0';
+    if (encrypt_flag)
+      strlcpy(args, "-x ", cc);
+    for (ap = argv; *ap; ap++) {
+      (void) strlcat(args, *ap, cc);
+	if (ap[1])
+	  strlcat(args, " ", cc);
+    }
+
+    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);
+	try_normal(argv0);
+    } 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-7/src/appl/bsd/krshd.c b/krb5-1-7/src/appl/bsd/krshd.c
new file mode 100644
index 000000000..080f2db12
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/krshd.c
@@ -0,0 +1,2047 @@
+/*
+ *	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)
+ * Execute command if configured authoriztion checks pass, else deny 
+ * permission.
+ */
+     
+/* DEFINES:
+ *   KERBEROS - Define this if application is to be kerberised.
+ *   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>
+#include <sys/socket.h>
+#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
+#include <stdarg.h>
+
+#include <signal.h>
+#include <netdb.h>
+
+#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 "k5-int.h"
+#include <com_err.h>
+#include "loginpaths.h"
+#include <k5-util.h>
+#include <k5-platform.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	"ek5ciD: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 */
+
+static int accept_a_connection (int debug_port, struct sockaddr *from,
+				socklen_t *fromlenp);
+     
+#ifndef HAVE_KILLPG
+#define killpg(pid, sig) kill(-(pid), (sig))
+#endif
+
+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':
+	break;
+	
+      case '5':
+	break;
+      case 'c':
+	checksum_required = 1;
+	break;
+      case 'i':
+	checksum_ignored = 1;
+	break;
+	
+        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;
+
+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 */
+	snprintf(ttyn,sizeof(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
+    /* 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);
+	error("Permission denied.\n");
+	goto signout_please;
+    }
+#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) {
+	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;
+    }
+    if (require_encrypt&&(!do_encrypt)) {
+	error("You must use encryption.\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);
+    if (asprintf(&path, "PATH=%s:%s", kprogdir, path_rest) < 0) {
+        perror("malloc");
+	_exit(1);
+    }
+    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;
+	if (asprintf(&buf2, "KRB5CCNAME=%s",getenv("KRB5CCNAME")) >= 0) {
+
+	  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;
+      snprintf(local_addr, sizeof(local_addr), "KRB5LOCALADDR=%s", hbuf);
+      envinit[i++] =local_addr;
+
+      snprintf(local_port, sizeof(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;
+      snprintf(remote_addr, sizeof(remote_addr), "KRB5REMOTEADDR=%s", hbuf);
+      envinit[i++] =remote_addr;
+
+      snprintf(remote_port, sizeof(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])) {
+		    if (asprintf(&buf2, "%s=%s", save_env[cnt], 
+				 getenv(save_env[cnt])) >= 0) {
+			    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 = strdup(cmdbuf);
+	if (copy == NULL) {
+	    perror("malloc");
+	    _exit(1);
+	}
+	if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
+		offst = 3;
+	}
+
+        strlcpy(cmdbuf + offst, kprogdir, sizeof(cmdbuf) - offst);
+	cp = copy + 3 + offst;
+
+	strlcat(cmdbuf, "/rcp", sizeof(cmdbuf));
+
+	if (stat((char *)cmdbuf + offst, &s2) >= 0)
+	  strlcat(cmdbuf, cp, sizeof(cmdbuf));
+	else
+	  strlcpy(cmdbuf, copy, sizeof(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) snprintf(cp, sizeof(buf) - (cp - buf), "%s: ", progname);
+    (void) vsnprintf(buf+strlen(buf), sizeof(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;
+    
+    snprintf(tdp, sizeof(tmpdir) - (tdp - tmpdir), "%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 [-eciK]  ");
+#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;
+    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
+
+    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;
+    }
+
+    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 */
+    if (status) {
+	/*
+	 * 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");
+
+    /* 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;
+	char namebuf[32];
+	krb5_boolean valid = 0;
+	krb5_data chksumbuf;
+
+	chksumbuf.data = NULL;
+	if (getsockname(netfd, (struct sockaddr *) &adr, &adr_length) != 0)
+	    goto error_cleanup;
+
+	e = getnameinfo((struct sockaddr *)&adr, adr_length, 0, 0,
+			namebuf, sizeof(namebuf), NI_NUMERICSERV);
+	if (e)
+	    fatal(netfd, "local error: can't examine port number");
+	if (asprintf(&chksumbuf.data, "%s:%s%s", namebuf, cmdbuf, locuser) < 0)
+	    goto error_cleanup;
+
+	chksumbuf.length = strlen(chksumbuf.data);
+	status = krb5_c_verify_checksum(bsd_context,
+					ticket->enc_part2->session,
+					KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+					&chksumbuf, authenticator->checksum,
+					&valid);
+	if (status == 0 && !valid) status = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+    error_cleanup:
+	if (chksumbuf.data)
+	    free(chksumbuf.data);
+	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) snprintf(buf + 1, sizeof(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);
+}
+
+static 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-7/src/appl/bsd/kshd.M b/krb5-1-7/src/appl/bsd/kshd.M
new file mode 100644
index 000000000..b6d50390a
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/login.M b/krb5-1-7/src/appl/bsd/login.M
new file mode 100644
index 000000000..3a1b05b4b
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/login.M
@@ -0,0 +1,77 @@
+.\"	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 (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\-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 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)
diff --git a/krb5-1-7/src/appl/bsd/login.c b/krb5-1-7/src/appl/bsd/login.c
new file mode 100644
index 000000000..57680ad3c
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/login.c
@@ -0,0 +1,1930 @@
+/*
+ *	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
+   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;
+
+#define KRB_RUN_AKLOG
+int login_krb_run_aklog = 0;
+
+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)
+ *
+ * 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 */
+
+#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 KRB5_GET_TICKETS
+#define MAXPWSIZE	128		/* Biggest string accepted for KRB5
+					   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},
+    {"krb_run_aklog", &login_krb_run_aklog},
+#endif
+};
+
+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 */
+
+void k_init (ttyn)
+    char *ttyn;
+{
+#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)) {
+	snprintf(ccfile, sizeof(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 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];			
+    snprintf(prompt, sizeof(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 */
+
+/* Kerberos ticket-handling routines */
+
+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
+}
+
+/* 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(SETPAG)
+    if (login_krb5_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_v5_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
+    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
+     */
+    (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;
+	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 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.
+    */
+
+    k_init (ttyn);
+
+    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;
+
+#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);
+
+		krbflag = got_v5_tickets;
+		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 */
+		}
+	    }
+
+	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 */
+
+#ifdef KRB5_GET_TICKETS
+    if (login_krb5_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 is created as root.  It needs 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 krbtgt 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 KRB5_GET_TICKETS
+    if (forwarded_v5_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 */
+
+    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 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)
+	    {
+		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) {
+	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)snprintf(tbuf, sizeof(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));
+}
+
+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;
+{
+    sleep((u_int)5);
+    exit(eval);
+}
+
+#ifdef KRB5_GET_TICKETS
+static int hungup = 0;
+
+static sigtype
+sighup() {
+    hungup = 1;
+}
+
+/* call already conditionalized on login_krb5_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 /* KRB5_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 = strdup(sp)) == NULL) {
+	fprintf(stderr, "no memory for saving args\n");
+	exit(1);
+    }
+    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-7/src/appl/bsd/loginpaths.h b/krb5-1-7/src/appl/bsd/loginpaths.h
new file mode 100644
index 000000000..0f2580bb9
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/rcp.M b/krb5-1-7/src/appl/bsd/rcp.M
new file mode 100644
index 000000000..a388e80ed
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/rlogin.M b/krb5-1-7/src/appl/bsd/rlogin.M
new file mode 100644
index 000000000..595884280
--- /dev/null
+++ b/krb5-1-7/src/appl/bsd/rlogin.M
@@ -0,0 +1,157 @@
+.\" 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\-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.
+.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-7/src/appl/bsd/rpaths.h b/krb5-1-7/src/appl/bsd/rpaths.h
new file mode 100644
index 000000000..4925ea33a
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/rsh.M b/krb5-1-7/src/appl/bsd/rsh.M
new file mode 100644
index 000000000..ce0ebfb20
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/bsd/setenv.c b/krb5-1-7/src/appl/bsd/setenv.c
new file mode 100644
index 000000000..0191d9c8c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/deps b/krb5-1-7/src/appl/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/gss-sample/Makefile.in b/krb5-1-7/src/appl/gss-sample/Makefile.in
new file mode 100644
index 000000000..e64e4871d
--- /dev/null
+++ b/krb5-1-7/src/appl/gss-sample/Makefile.in
@@ -0,0 +1,51 @@
+thisconfigdir=../..
+myfulldir=appl/gss-sample
+mydir=appl/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
diff --git a/krb5-1-7/src/appl/gss-sample/README b/krb5-1-7/src/appl/gss-sample/README
new file mode 100644
index 000000000..dc51fca1b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gss-sample/deps b/krb5-1-7/src/appl/gss-sample/deps
new file mode 100644
index 000000000..34495ea98
--- /dev/null
+++ b/krb5-1-7/src/appl/gss-sample/deps
@@ -0,0 +1,12 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(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/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-7/src/appl/gss-sample/gss-client.c b/krb5-1-7/src/appl/gss-sample/gss-client.c
new file mode 100644
index 000000000..390d6e56f
--- /dev/null
+++ b/krb5-1-7/src/appl/gss-sample/gss-client.c
@@ -0,0 +1,812 @@
+/*
+ * 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;
+    gss_buffer_desc tok;
+    OM_uint32 maj_stat, min_stat;
+    size_t i, mechlen = strlen(mechanism);
+
+    if (isdigit((int) mechanism[0])) {
+	mechstr = malloc(mechlen + 5);
+	if (!mechstr) {
+	    fprintf(stderr, "Couldn't allocate mechanism scratch!\n");
+	    return;
+	}
+	mechstr[0] = '{';
+	mechstr[1] = ' ';
+	for (i = 0; i < mechlen; i++)
+	  mechstr[i + 2] = (mechanism[i] == '.') ? ' ' : mechanism[i];
+	mechstr[mechlen + 2] = ' ';
+	mechstr[mechlen + 3] = ' ';
+	mechstr[mechlen + 4] = '\0';
+	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-7/src/appl/gss-sample/gss-misc.c b/krb5-1-7/src/appl/gss-sample/gss-misc.c
new file mode 100644
index 000000000..cfaa0f8bd
--- /dev/null
+++ b/krb5-1-7/src/appl/gss-sample/gss-misc.c
@@ -0,0 +1,428 @@
+/*
+ * 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 */
+#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-7/src/appl/gss-sample/gss-misc.h b/krb5-1-7/src/appl/gss-sample/gss-misc.h
new file mode 100644
index 000000000..35b3b7390
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gss-sample/gss-server.c b/krb5-1-7/src/appl/gss-sample/gss-server.c
new file mode 100644
index 000000000..488f14ccc
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/Makefile.in b/krb5-1-7/src/appl/gssftp/Makefile.in
new file mode 100644
index 000000000..959316fcb
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/Makefile.in
@@ -0,0 +1,6 @@
+thisconfigdir=.
+myfulldir=appl/gssftp
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=ftp ftpd
+LDFLAGS = -g
diff --git a/krb5-1-7/src/appl/gssftp/README.gssftp b/krb5-1-7/src/appl/gssftp/README.gssftp
new file mode 100644
index 000000000..e0dff5200
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/arpa/ftp.h b/krb5-1-7/src/appl/gssftp/arpa/ftp.h
new file mode 100644
index 000000000..e20285c4c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/arpa/telnet.h b/krb5-1-7/src/appl/gssftp/arpa/telnet.h
new file mode 100644
index 000000000..019bfeb60
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/configure.in b/krb5-1-7/src/appl/gssftp/configure.in
new file mode 100644
index 000000000..e483b649c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/deps b/krb5-1-7/src/appl/gssftp/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/gssftp/ftp/Makefile.in b/krb5-1-7/src/appl/gssftp/ftp/Makefile.in
new file mode 100644
index 000000000..8026f1e22
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/Makefile.in
@@ -0,0 +1,65 @@
+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)
+
+all-unix::	ftp
+all-windows::	$(OUTPRE)ftp.exe
+
+ftp:	$(OBJS) $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o ftp $(OBJS) $(GSS_LIBS) $(KRB5_BASE_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
diff --git a/krb5-1-7/src/appl/gssftp/ftp/cmds.c b/krb5-1-7/src/appl/gssftp/ftp/cmds.c
new file mode 100644
index 000000000..b7f8d8d80
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/cmds.c
@@ -0,0 +1,2533 @@
+/*
+ * 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 _WIN32
+#include <win-mac.h>
+#endif
+
+#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>
+
+#include <k5-platform.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) strlcpy(bytename, "8", sizeof(bytename)), 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();
+		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) snprintf(shellnam, sizeof(shellnam), "-%s", ++namep);
+		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-7/src/appl/gssftp/ftp/cmdtab.c b/krb5-1-7/src/appl/gssftp/ftp/cmdtab.c
new file mode 100644
index 000000000..cfa11e371
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftp/deps b/krb5-1-7/src/appl/gssftp/ftp/deps
new file mode 100644
index 000000000..7cee7b57c
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/deps
@@ -0,0 +1,28 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)cmds.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.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_ext.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.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): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  ftp_var.h glob.c
+$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.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 \
+  $(srcdir)/../arpa/ftp.h secure.c secure.h
diff --git a/krb5-1-7/src/appl/gssftp/ftp/domacro.c b/krb5-1-7/src/appl/gssftp/ftp/domacro.c
new file mode 100644
index 000000000..e15196a6c
--- /dev/null
+++ b/krb5-1-7/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 <signal.h>
+
+#include "ftp_var.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-7/src/appl/gssftp/ftp/ftp.M b/krb5-1-7/src/appl/gssftp/ftp/ftp.M
new file mode 100644
index 000000000..11bbc931e
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/ftp.M
@@ -0,0 +1,1127 @@
+.\" 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
+.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-7/src/appl/gssftp/ftp/ftp.c b/krb5-1-7/src/appl/gssftp/ftp/ftp.c
new file mode 100644
index 000000000..3df233fcd
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/ftp.c
@@ -0,0 +1,2233 @@
+/*
+ * 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>
+#include <sys/socket.h>
+#include <netdb.h>
+#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
+
+#include <k5-platform.h>
+
+#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) strlcpy(line, "$init", sizeof(line));
+			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 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) %lu bytes\n",
+					  clevel==PROT_P?"ENC":"MIC", 
+					  (unsigned long) 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);
+	vsnprintf(in, FTP_BUFSIZ, 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 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);
+				    memcpy(&ibuf[msg_buf.length], "\r\n", 3);
+				  } 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;
+	} 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;
+	(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 GSSAPI
+static const struct {
+    gss_OID mech_type;
+    char *service_name;
+} gss_trials[] = {
+    { GSS_C_NO_OID, "ftp" },
+    { GSS_C_NO_OID, "host" },
+};
+static const int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
+#endif /* GSSAPI */
+
+int do_auth()
+{
+	int oldverbose = verbose;
+#ifdef GSSAPI
+	u_char out_buf[FTP_BUFSIZ];
+	int i;
+#endif /* GSSAPI */
+
+	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... */
+	    snprintf(stbuf, sizeof(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 */
+
+	/* 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
+	 */
+	snprintf(buf, sizeof(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-7/src/appl/gssftp/ftp/ftp_var.h b/krb5-1-7/src/appl/gssftp/ftp/ftp_var.h
new file mode 100644
index 000000000..39386ff1d
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/ftp_var.h
@@ -0,0 +1,288 @@
+/*
+ * 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 *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
+
+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-7/src/appl/gssftp/ftp/getpass.c b/krb5-1-7/src/appl/gssftp/ftp/getpass.c
new file mode 100644
index 000000000..cd27cdce5
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftp/glob.c b/krb5-1-7/src/appl/gssftp/ftp/glob.c
new file mode 100644
index 000000000..bbbcb4457
--- /dev/null
+++ b/krb5-1-7/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 <k5-platform.h>
+
+#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) memmove(gpath, gpath + 1,
+					       strlen(gpath));
+			} 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;
+
+	if (asprintf(&buffer, "%s\\*", base) < 0) return;
+	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;
+{
+	char *ep;
+
+	if (asprintf(&ep, "%s%s", cp, dp) < 0)
+		fatal("Out of memory");
+	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);
+	size_t bufsize = lastgpathp - mhome;
+
+	if (!pp)
+		return (1);
+	if (strlcpy(mhome, pp->pw_dir, bufsize) >= bufsize)
+		return (1);
+	return (0);
+}
+#endif
diff --git a/krb5-1-7/src/appl/gssftp/ftp/main.c b/krb5-1-7/src/appl/gssftp/ftp/main.c
new file mode 100644
index 000000000..6ec5ee1a8
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/main.c
@@ -0,0 +1,606 @@
+/*
+ * 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 <signal.h>
+#include "ftp_var.h"
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#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 <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();
+
+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);
+	}
+	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;
+
+			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-7/src/appl/gssftp/ftp/pathnames.h b/krb5-1-7/src/appl/gssftp/ftp/pathnames.h
new file mode 100644
index 000000000..7c0de5b0e
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftp/pclose.c b/krb5-1-7/src/appl/gssftp/ftp/pclose.c
new file mode 100644
index 000000000..5d6a5aa57
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftp/radix.c b/krb5-1-7/src/appl/gssftp/ftp/radix.c
new file mode 100644
index 000000000..2d6dfd18d
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftp/ruserpass.c b/krb5-1-7/src/appl/gssftp/ftp/ruserpass.c
new file mode 100644
index 000000000..6e603e459
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/ruserpass.c
@@ -0,0 +1,293 @@
+/*
+ * 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) snprintf(buf, sizeof(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 = strdup(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 = strdup(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 = strdup(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-7/src/appl/gssftp/ftp/secure.c b/krb5-1-7/src/appl/gssftp/ftp/secure.c
new file mode 100644
index 000000000..3ed15ee97
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/secure.c
@@ -0,0 +1,410 @@
+/*
+ * 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 _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 */
+
+/* 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 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 = 0;
+	ftp_uint32 net_len;
+	unsigned int fudge = smaxbuf - smaxqueue; /* Difference in length
+						     buffer lengths required */
+
+	/* Other auth types go here ... */
+#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 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-7/src/appl/gssftp/ftp/secure.h b/krb5-1-7/src/appl/gssftp/ftp/secure.h
new file mode 100644
index 000000000..011d745f6
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftp/secure.h
@@ -0,0 +1,19 @@
+#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 *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
diff --git a/krb5-1-7/src/appl/gssftp/ftpd/CHANGES b/krb5-1-7/src/appl/gssftp/ftpd/CHANGES
new file mode 100644
index 000000000..39c7ebda0
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftpd/Makefile.in b/krb5-1-7/src/appl/gssftp/ftpd/Makefile.in
new file mode 100644
index 000000000..8e96a32fe
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftpd/Makefile.in
@@ -0,0 +1,78 @@
+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)
+
+all::	ftpd
+
+ftpd:	$(OBJS) $(PTY_DEPLIB) $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ $(OBJS) $(FTPD_LIBS) $(PTY_LIB) $(UTIL_LIB) $(GSS_LIBS) $(KRB5_BASE_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
diff --git a/krb5-1-7/src/appl/gssftp/ftpd/deps b/krb5-1-7/src/appl/gssftp/ftpd/deps
new file mode 100644
index 000000000..1d0d3558f
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftpd/deps
@@ -0,0 +1,29 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)ftpd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.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 $(SRCTOP)/include/k5-buf.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): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(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 \
+  $(srcdir)/../arpa/ftp.h $(srcdir)/../ftp/secure.c secure.h
+$(OUTPRE)getdtablesize.$(OBJEXT): $(srcdir)/../../bsd/getdtablesize.c
diff --git a/krb5-1-7/src/appl/gssftp/ftpd/ftpcmd.y b/krb5-1-7/src/appl/gssftp/ftpd/ftpcmd.y
new file mode 100644
index 000000000..a57b43587
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftpd/ftpcmd.y
@@ -0,0 +1,1532 @@
+/* -*- 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 <k5-buf.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 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 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);
+		memcpy(s+msg_buf.length-(s[msg_buf.length-1]?0:1), "\r\n", 3);
+		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;
+	    }
+
+	}
+#ifdef 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 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 = strdup(s);
+	if (p == NULL)
+		fatal("Ran out of memory.");
+	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;
+		struct k5buf buf;
+
+		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++) {
+			krb5int_buf_init_fixed(&buf, str, sizeof(str));
+			krb5int_buf_add(&buf, "   ");
+			for (j = 0; j < columns; j++) {
+				c = ctab + j * lines + i;
+				krb5int_buf_add_fmt(&buf, "%s%c", c->name,
+						    c->implemented ? ' '
+						    : '*');
+				if (c + lines >= &ctab[NCMDS])
+					break;
+				w = strlen(c->name) + 1;
+				while (w < width) {
+					krb5int_buf_add(&buf, " ");
+					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-7/src/appl/gssftp/ftpd/ftpd.M b/krb5-1-7/src/appl/gssftp/ftpd/ftpd.M
new file mode 100644
index 000000000..5cdc9b353
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftpd/ftpd.M
@@ -0,0 +1,501 @@
+.\" 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\-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-7/src/appl/gssftp/ftpd/ftpd.c b/krb5-1-7/src/appl/gssftp/ftpd/ftpd.c
new file mode 100644
index 000000000..d8278128c
--- /dev/null
+++ b/krb5-1-7/src/appl/gssftp/ftpd/ftpd.c
@@ -0,0 +1,2726 @@
+/*
+ * 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>
+#include <sys/socket.h>
+#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
+#include <netdb.h>
+#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>
+
+#include <k5-platform.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 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 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;
+	char *option_string = "AaCcdElp:T:t:U:u:vw:";
+	ftpusers = _PATH_FTPUSERS_DEFAULT;
+
+	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 '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 = strdup(s);
+
+	if (new == NULL) {
+		perror_reply(421, "Local resource failure: malloc");
+		dologout(1);
+		/* NOTREACHED */
+	}
+	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]";
+			}
+			snprintf(buf, sizeof(buf),
+				 "GSSAPI user %s is%s authorized as %s",
+				(char *) client_name.value, 
+				authorized ? "" : " not",
+				name);
+		}
+#endif /* GSSAPI */
+
+		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;
+		if (result == 232)
+			login(NULL, result);
+		reply(result, "%s", buf);
+		syslog(authorized ? LOG_INFO : LOG_ERR, "%s", buf);
+		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
+		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 */
+	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;
+
+	snprintf(ccname, sizeof(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);
+	}
+
+	have_creds = 1;
+	return(1);
+#endif /* GSSAPI */
+
+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
+	}
+
+	(void) krb5_setegid((gid_t)pw->pw_gid);
+	(void) initgroups(pw->pw_name, pw->pw_gid);
+
+	/* open wtmp before chroot */
+	(void) snprintf(ttyline, sizeof(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
+		snprintf(proctitle, sizeof(proctitle), "%s: anonymous/%.*s",
+			 rhost_sane, 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
+		snprintf(proctitle, sizeof(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) snprintf(line, sizeof(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) snprintf (sizebuf, sizeof(sizebuf), " (%ld bytes)",
+				 (long)size);
+	else
+		sizebuf[0] = '\0';
+	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
+ */
+void
+secure_error(char *fmt, ...)
+{
+	char buf[FTP_BUFSIZ];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+	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) snprintf(line, sizeof(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);
+	snprintf(str, sizeof(str), "     Connected to %s (%s)",
+		 remotehost[0] ? remotehost : "", 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]);
+	snprintf(str, sizeof(str), "     TYPE: %s", typenames[type]);
+	if (type == TYPE_A || type == TYPE_E) {
+		snprintf(&str[strlen(str)], sizeof(str) - strlen(str),
+			 ", FORM: %s", formnames[form]);
+	}
+	if (type == TYPE_L)
+		strncat(str, " 8", sizeof (str) - strlen(str) - 1);
+	snprintf(&str[strlen(str)], sizeof(str) - strlen(str),
+		 "; STRUcture: %s; transfer MODE: %s",
+		 strunames[stru], modenames[mode]);
+	reply(0, "%s", str);
+	if (data != -1)
+		strlcpy(str, "     Data connection open", sizeof(str));
+	else if (pdata != -1) {
+		strlcpy(str, "     in Passive mode", sizeof(str));
+		sin4 = &pasv_addr;
+		goto printaddr;
+	} else if (usedefault == 0) {
+		sin4 = &data_dest;
+printaddr:
+		a = (u_char *) &sin4->sin_addr;
+		p = (u_char *) &sin4->sin_port;
+#define UC(b) (((int) b) & 0xff)
+		snprintf(str, sizeof(str), "     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]));
+#undef UC
+	} else
+		strlcpy(str, "     No data connection", sizeof(str));
+	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);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+#else
+	snprintf(buf, sizeof(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 = 0, kerror;
+		if (n) snprintf(in, sizeof(in), "%d%c", n, cont_char);
+		else in[0] = '\0';
+		strncat(in, buf, sizeof (in) - strlen(in) - 1);
+#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);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+#else
+	snprintf(buf, sizeof(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
+	snprintf(proctitle, sizeof(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
+	}
+	/* 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) snprintf(cp, sizeof(new) - (cp - new), "%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 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;
+
+	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 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++) {
+			snprintf(service_name, sizeof(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
+ */
+static int
+secure_fprintf(FILE *stream, char *fmt, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 2, 3)))
+#endif
+    ;
+
+static int
+secure_fprintf(FILE *stream, char *fmt, ...)
+{
+        char s[FTP_BUFSIZ];
+        int rval;
+        va_list ap;
+
+        va_start(ap, fmt);
+        if (dlevel == PROT_C) rval = vfprintf(stream, fmt, ap);
+        else {
+		vsnprintf(s, sizeof(s), fmt, ap);
+                rval = secure_write(fileno(stream), s, strlen(s));
+        }
+        va_end(ap);
+
+        return(rval);
+}
+
+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;
+			}
+			snprintf(nbuf, sizeof(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];
+
+	/* Set up ccache */
+	if (krb5_parse_name(kcontext, name, &me))
+		return;
+
+	snprintf(ccname, sizeof(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;
+
+	have_creds = 1;
+	return;
+
+cleanup:
+	krb5_cc_destroy(kcontext, ccache);
+}
+
+
+#endif /* GSSAPI */
+
diff --git a/krb5-1-7/src/appl/gssftp/ftpd/ftpd_var.h b/krb5-1-7/src/appl/gssftp/ftpd/ftpd_var.h
new file mode 100644
index 000000000..8d833e4ec
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftpd/logwtmp.c b/krb5-1-7/src/appl/gssftp/ftpd/logwtmp.c
new file mode 100644
index 000000000..06b97b986
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftpd/pathnames.h b/krb5-1-7/src/appl/gssftp/ftpd/pathnames.h
new file mode 100644
index 000000000..41398bc5f
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftpd/popen.c b/krb5-1-7/src/appl/gssftp/ftpd/popen.c
new file mode 100644
index 000000000..e9e589594
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/gssftp/ftpd/secure.h b/krb5-1-7/src/appl/gssftp/ftpd/secure.h
new file mode 100644
index 000000000..21b7ff836
--- /dev/null
+++ b/krb5-1-7/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);
+
+void secure_error(char *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
diff --git a/krb5-1-7/src/appl/gssftp/ftpd/vers.c b/krb5-1-7/src/appl/gssftp/ftpd/vers.c
new file mode 100644
index 000000000..76846bda7
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/Makefile.in b/krb5-1-7/src/appl/libpty/Makefile.in
new file mode 100644
index 000000000..924ef1b9b
--- /dev/null
+++ b/krb5-1-7/src/appl/libpty/Makefile.in
@@ -0,0 +1,112 @@
+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)
+
+@libpriv_frag@
+@lib_frag@
+@libobj_frag@
+
diff --git a/krb5-1-7/src/appl/libpty/README b/krb5-1-7/src/appl/libpty/README
new file mode 100644
index 000000000..f10dd2b37
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/cleanup.c b/krb5-1-7/src/appl/libpty/cleanup.c
new file mode 100644
index 000000000..57cc796ac
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/configure.in b/krb5-1-7/src/appl/libpty/configure.in
new file mode 100644
index 000000000..22af7023d
--- /dev/null
+++ b/krb5-1-7/src/appl/libpty/configure.in
@@ -0,0 +1,262 @@
+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
+KRB5_BUILD_LIBRARY
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_PROGRAM
+KRB5_RUN_FLAGS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-7/src/appl/libpty/deps b/krb5-1-7/src/appl/libpty/deps
new file mode 100644
index 000000000..841f6630e
--- /dev/null
+++ b/krb5-1-7/src/appl/libpty/deps
@@ -0,0 +1,45 @@
+# 
+# Generated makefile dependencies follow.
+#
+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/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(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/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(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-7/src/appl/libpty/dump-utmp.c b/krb5-1-7/src/appl/libpty/dump-utmp.c
new file mode 100644
index 000000000..d4c303fb3
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/getpty.c b/krb5-1-7/src/appl/libpty/getpty.c
new file mode 100644
index 000000000..e5bf2854b
--- /dev/null
+++ b/krb5-1-7/src/appl/libpty/getpty.c
@@ -0,0 +1,149 @@
+/*
+ * 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"
+#include "k5-platform.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 (strlcpy(slave, slaveret, slavelength) >= slavelength) {
+	close(*fd);
+	*fd = -1;
+	return PTY_GETPTY_SLAVE_TOOLONG;
+    }
+    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 (strlcpy(slave, p, slavelength) >= slavelength) {
+		    close (*fd);
+		    *fd = -1;
+		    return PTY_GETPTY_SLAVE_TOOLONG;
+	    }
+	    return 0;
+	}
+
+	if (fstat(*fd, &stb) < 0) {
+	    close(*fd);
+	    return PTY_GETPTY_FSTAT;
+	}
+	ptynum = (int)(stb.st_rdev&0xFF);
+	snprintf(slavebuf, sizeof(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++) {
+	    snprintf(slavebuf,sizeof(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-7/src/appl/libpty/init.c b/krb5-1-7/src/appl/libpty/init.c
new file mode 100644
index 000000000..b48a1f8a7
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/init_slave.c b/krb5-1-7/src/appl/libpty/init_slave.c
new file mode 100644
index 000000000..ce7507645
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/libpty.h b/krb5-1-7/src/appl/libpty/libpty.h
new file mode 100644
index 000000000..d95c8fe08
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/logwtmp.c b/krb5-1-7/src/appl/libpty/logwtmp.c
new file mode 100644
index 000000000..03cfab48f
--- /dev/null
+++ b/krb5-1-7/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;
+    snprintf(utmp_id, sizeof(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-7/src/appl/libpty/open_ctty.c b/krb5-1-7/src/appl/libpty/open_ctty.c
new file mode 100644
index 000000000..5a1730b31
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/open_slave.c b/krb5-1-7/src/appl/libpty/open_slave.c
new file mode 100644
index 000000000..5bab6bc36
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/pty-int.h b/krb5-1-7/src/appl/libpty/pty-int.h
new file mode 100644
index 000000000..b94a65c0e
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/pty_err.et b/krb5-1-7/src/appl/libpty/pty_err.et
new file mode 100644
index 000000000..770cce7a9
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/pty_paranoia.c b/krb5-1-7/src/appl/libpty/pty_paranoia.c
new file mode 100644
index 000000000..466a65888
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/sane_hostname.c b/krb5-1-7/src/appl/libpty/sane_hostname.c
new file mode 100644
index 000000000..8ef6de875
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/update_utmp.c b/krb5-1-7/src/appl/libpty/update_utmp.c
new file mode 100644
index 000000000..292a1675b
--- /dev/null
+++ b/krb5-1-7/src/appl/libpty/update_utmp.c
@@ -0,0 +1,724 @@
+/*
+ * 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"
+#include "k5-platform.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
+    strlcpy(utmp_id, cp, sizeof(utmp_id));
+#else
+    if (len > 2 && *(cp - 1) != '/')
+	snprintf(utmp_id, sizeof(utmp_id), "k%s", cp - 1);
+    else
+	snprintf(utmp_id, sizeof(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-7/src/appl/libpty/update_wtmp.c b/krb5-1-7/src/appl/libpty/update_wtmp.c
new file mode 100644
index 000000000..988bae61a
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/vhangup.c b/krb5-1-7/src/appl/libpty/vhangup.c
new file mode 100644
index 000000000..292437142
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/libpty/void_assoc.c b/krb5-1-7/src/appl/libpty/void_assoc.c
new file mode 100644
index 000000000..a39c9c723
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/sample/Makefile.in b/krb5-1-7/src/appl/sample/Makefile.in
new file mode 100644
index 000000000..819444636
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=../..
+myfulldir=appl/sample
+mydir=appl/sample
+SUBDIRS = sclient sserver
+BUILDTOP=$(REL)..$(S)..
diff --git a/krb5-1-7/src/appl/sample/deps b/krb5-1-7/src/appl/sample/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/sample/sample.h b/krb5-1-7/src/appl/sample/sample.h
new file mode 100644
index 000000000..6c81d9351
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/sample/sclient/Makefile.in b/krb5-1-7/src/appl/sample/sclient/Makefile.in
new file mode 100644
index 000000000..db69a1375
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sclient/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=../../..
+myfulldir=appl/sample/sclient
+mydir=appl/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-7/src/appl/sample/sclient/deps b/krb5-1-7/src/appl/sample/sclient/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sclient/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/sample/sclient/sclient.M b/krb5-1-7/src/appl/sample/sclient/sclient.M
new file mode 100644
index 000000000..1b5a8d6b7
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/sample/sclient/sclient.c b/krb5-1-7/src/appl/sample/sclient/sclient.c
new file mode 100644
index 000000000..bd9c4e889
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sclient/sclient.c
@@ -0,0 +1,260 @@
+/*
+ * 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));
+	    memset(pbuf, 0, sizeof(pbuf));
+	    strncpy(abuf, "[error, cannot print address?]",
+		    sizeof(abuf)-1);
+	    strncpy(pbuf, "[?]", sizeof(pbuf)-1);
+	}
+	memset(mbuf, 0, sizeof(mbuf));
+	strncpy(mbuf, "error contacting ", sizeof(mbuf)-1);
+	strncat(mbuf, abuf, sizeof(mbuf) - strlen(mbuf) - 1);
+	strncat(mbuf, " port ", sizeof(mbuf) - strlen(mbuf) - 1);
+	strncat(mbuf, pbuf, sizeof(mbuf) - strlen(mbuf) - 1);
+	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-7/src/appl/sample/sserver/Makefile.in b/krb5-1-7/src/appl/sample/sserver/Makefile.in
new file mode 100644
index 000000000..e5ca92f69
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sserver/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=../../..
+myfulldir=appl/sample/sserver
+mydir=appl/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-7/src/appl/sample/sserver/deps b/krb5-1-7/src/appl/sample/sserver/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sserver/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/sample/sserver/sserver.M b/krb5-1-7/src/appl/sample/sserver/sserver.M
new file mode 100644
index 000000000..4323fd11b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/sample/sserver/sserver.c b/krb5-1-7/src/appl/sample/sserver/sserver.c
new file mode 100644
index 000000000..39710fb2b
--- /dev/null
+++ b/krb5-1-7/src/appl/sample/sserver/sserver.c
@@ -0,0 +1,245 @@
+/*
+ * 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 "k5-int.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 */
+    repbuf[sizeof(repbuf) - 1] = '\0';
+    retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname);
+    if (retval){
+	syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
+	strncpy(repbuf, "You are <unparse error>\n", sizeof(repbuf) - 1);
+    } else {
+	strncpy(repbuf, "You are ", sizeof(repbuf) - 1);
+	strncat(repbuf, cname, sizeof(repbuf) - 1 - strlen(repbuf));
+	strncat(repbuf, "\n", sizeof(repbuf) - 1 - strlen(repbuf));
+	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-7/src/appl/simple/Makefile.in b/krb5-1-7/src/appl/simple/Makefile.in
new file mode 100644
index 000000000..c6b7baae7
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=../..
+myfulldir=appl/simple
+mydir=appl/simple
+SUBDIRS = client server
+BUILDTOP=$(REL)..$(S)..
diff --git a/krb5-1-7/src/appl/simple/client/Makefile.in b/krb5-1-7/src/appl/simple/client/Makefile.in
new file mode 100644
index 000000000..c6840fe2b
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/client/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=../../..
+myfulldir=appl/simple/client
+mydir=appl/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-7/src/appl/simple/client/deps b/krb5-1-7/src/appl/simple/client/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/client/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/simple/client/sim_client.c b/krb5-1-7/src/appl/simple/client/sim_client.c
new file mode 100644
index 000000000..4873f89af
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/client/sim_client.c
@@ -0,0 +1,338 @@
+/*
+ * 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 <k5-int.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);
+
+    retval = krb5_rc_destroy(context, rcache);
+    if (retval) {
+	com_err(progname, retval, "while deleting replay cache");
+	exit(1);
+    }
+    krb5_auth_con_setrcache(context, auth_context, NULL);
+    krb5_auth_con_free(context, auth_context);
+    krb5_free_context(context);
+    
+    exit(0);
+}
diff --git a/krb5-1-7/src/appl/simple/deps b/krb5-1-7/src/appl/simple/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/simple/server/Makefile.in b/krb5-1-7/src/appl/simple/server/Makefile.in
new file mode 100644
index 000000000..12b2b04ad
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/server/Makefile.in
@@ -0,0 +1,20 @@
+thisconfigdir=../../..
+myfulldir=appl/simple/server
+mydir=appl/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-7/src/appl/simple/server/deps b/krb5-1-7/src/appl/simple/server/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/simple/server/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/simple/server/sim_server.c b/krb5-1-7/src/appl/simple/server/sim_server.c
new file mode 100644
index 000000000..137cc49f0
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/simple/simple.h b/krb5-1-7/src/appl/simple/simple.h
new file mode 100644
index 000000000..f230592e6
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/Config.generic b/krb5-1-7/src/appl/telnet/Config.generic
new file mode 100644
index 000000000..c6f88a52b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/Makefile.in b/krb5-1-7/src/appl/telnet/Makefile.in
new file mode 100644
index 000000000..716b4580b
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=.
+myfulldir=appl/telnet
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=libtelnet telnet telnetd
diff --git a/krb5-1-7/src/appl/telnet/README b/krb5-1-7/src/appl/telnet/README
new file mode 100644
index 000000000..29d51a392
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/arpa/telnet.h b/krb5-1-7/src/appl/telnet/arpa/telnet.h
new file mode 100644
index 000000000..f6d0eb566
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/configure.in b/krb5-1-7/src/appl/telnet/configure.in
new file mode 100644
index 000000000..fc91a5a82
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/configure.in
@@ -0,0 +1,164 @@
+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
+KRB5_BUILD_LIBRARY
+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 "$ac_cv_c_compiler_gnu" = 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
+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-7/src/appl/telnet/deps b/krb5-1-7/src/appl/telnet/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/telnet/kern.diff b/krb5-1-7/src/appl/telnet/kern.diff
new file mode 100644
index 000000000..3c1153bab
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/Makefile.in b/krb5-1-7/src/appl/telnet/libtelnet/Makefile.in
new file mode 100644
index 000000000..2b8aff220
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/Makefile.in
@@ -0,0 +1,89 @@
+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)/..
+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)/kerberos5.c \
+	$(srcdir)/forward.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 kerberos5.o forward.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
+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::
+
+@libpriv_frag@
+@lib_frag@
+@libobj_frag@
+
diff --git a/krb5-1-7/src/appl/telnet/libtelnet/auth-proto.h b/krb5-1-7/src/appl/telnet/libtelnet/auth-proto.h
new file mode 100644
index 000000000..faf806fad
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/auth-proto.h
@@ -0,0 +1,98 @@
+/*-
+ * 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	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-7/src/appl/telnet/libtelnet/auth.c b/krb5-1-7/src/appl/telnet/libtelnet/auth.c
new file mode 100644
index 000000000..1a1006605
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/auth.c
@@ -0,0 +1,651 @@
+/*-
+ * 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
+	{ 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++) {
+		snprintf((char *)tbuf, sizeof(tbuf), " %d", *data);
+		for (cp = tbuf; *cp && buflen > 0; --buflen)
+			*buf++ = *cp++;
+		if (buflen <= 0)
+			return;
+	}
+	*buf = '\0';
+}
+#endif
diff --git a/krb5-1-7/src/appl/telnet/libtelnet/auth.h b/krb5-1-7/src/appl/telnet/libtelnet/auth.h
new file mode 100644
index 000000000..f9f31d8e7
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/deps b/krb5-1-7/src/appl/telnet/libtelnet/deps
new file mode 100644
index 000000000..09cecf0d4
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/deps
@@ -0,0 +1,38 @@
+# 
+# Generated makefile dependencies follow.
+#
+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
+kerberos5.so kerberos5.po $(OUTPRE)kerberos5.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.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
+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-7/src/appl/telnet/libtelnet/enc-proto.h b/krb5-1-7/src/appl/telnet/libtelnet/enc-proto.h
new file mode 100644
index 000000000..eed7db66b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/enc_des.c b/krb5-1-7/src/appl/telnet/libtelnet/enc_des.c
new file mode 100644
index 000000000..aa00ae27e
--- /dev/null
+++ b/krb5-1-7/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:
+		snprintf(lbuf, sizeof(lbuf), "%s_IV", type);
+		cp = lbuf;
+		goto common;
+
+	case FB64_IV_OK:
+		snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type);
+		cp = lbuf;
+		goto common;
+
+	case FB64_IV_BAD:
+		snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type);
+		cp = lbuf;
+		goto common;
+
+	default:
+		snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]);
+		cp = lbuf;
+	common:
+		for (; (buflen > 0) && (*buf = *cp++); buf++)
+			buflen--;
+		for (i = 3; i < cnt; i++) {
+			snprintf(lbuf, sizeof(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-7/src/appl/telnet/libtelnet/encrypt.c b/krb5-1-7/src/appl/telnet/libtelnet/encrypt.c
new file mode 100644
index 000000000..6317eceb3
--- /dev/null
+++ b/krb5-1-7/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++) {
+		snprintf(tbuf, sizeof(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-7/src/appl/telnet/libtelnet/encrypt.h b/krb5-1-7/src/appl/telnet/libtelnet/encrypt.h
new file mode 100644
index 000000000..4efac570b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/forward.c b/krb5-1-7/src/appl/telnet/libtelnet/forward.c
new file mode 100644
index 000000000..98dcb7897
--- /dev/null
+++ b/krb5-1-7/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);
+
+    snprintf(ccname, sizeof(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-7/src/appl/telnet/libtelnet/genget.c b/krb5-1-7/src/appl/telnet/libtelnet/genget.c
new file mode 100644
index 000000000..bc307c81f
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/getent.c b/krb5-1-7/src/appl/telnet/libtelnet/getent.c
new file mode 100644
index 000000000..b80439e6e
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/getopt.c b/krb5-1-7/src/appl/telnet/libtelnet/getopt.c
new file mode 100644
index 000000000..d61cc3c1f
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/gettytab.c b/krb5-1-7/src/appl/telnet/libtelnet/gettytab.c
new file mode 100644
index 000000000..d50f8797e
--- /dev/null
+++ b/krb5-1-7/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;
+	}
+	strlcpy(p, q+1, TABBUFSIZ - (p-tbuf));
+	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-7/src/appl/telnet/libtelnet/gettytab.h b/krb5-1-7/src/appl/telnet/libtelnet/gettytab.h
new file mode 100644
index 000000000..02e5050a8
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/herror.c b/krb5-1-7/src/appl/telnet/libtelnet/herror.c
new file mode 100644
index 000000000..3b20f807f
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/kerberos5.c b/krb5-1-7/src/appl/telnet/libtelnet/kerberos5.c
new file mode 100644
index 000000000..40eb184ac
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/kerberos5.c
@@ -0,0 +1,901 @@
+/*
+ *	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 "k5-platform.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 = strdup(telnet_krb5_realm);
+	    if (rdata.data == NULL) {
+	        fprintf(stderr, "malloc failed\n");
+		return(0);
+	    }
+	    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) snprintf(errbuf, sizeof(errbuf),
+					"krb5_rd_req failed: %s",
+					error_message(r));
+			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) strlcpy(errbuf, "malformed service name",
+				   sizeof(errbuf));
+		    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) snprintf(errbuf, sizeof(errbuf), "incorrect service name: \"%s\" != \"host\"",
+                                           princ);
+                        } else {
+                            (void) snprintf(errbuf, sizeof(errbuf), "incorrect service name: principal != \"host\"");
+                        }
+			goto errout;
+		    }
+		} else {
+		    (void) strlcpy(errbuf, "service name too long",
+				   sizeof(errbuf));
+		    goto errout;
+		}
+
+		r = krb5_auth_con_getauthenticator(telnet_context,
+						   auth_context,
+						   &authenticator);
+		if (r) {
+			(void) snprintf(errbuf, sizeof(errbuf),
+					"krb5_auth_con_getauthenticator failed: %s",
+					error_message(r));
+			goto errout;
+		}
+		if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
+		    !authenticator->checksum) {
+			(void) strlcpy(errbuf,
+				"authenticator is missing required checksum",
+				       sizeof(errbuf));
+			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) snprintf(errbuf, sizeof(errbuf),
+					"krb5_auth_con_getkey failed: %s",
+					error_message(r));
+			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) snprintf(errbuf, sizeof(errbuf),
+					"checksum verification failed: %s",
+					error_message(r));
+			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) snprintf(errbuf, sizeof(errbuf),
+					"Make reply failed: %s",
+					error_message(r));
+			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) snprintf(kerrbuf, sizeof(kerrbuf),
+				    "Read forwarded creds failed: %s",
+				    error_message(r));
+		    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];
+
+	    snprintf(eerrbuf, sizeof(eerrbuf), "telnetd: %s", errbuf);
+	    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:
+		snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[3]);
+		strncpy((char *)buf, lbuf, buflen);
+	common2:
+		BUMP(buf, buflen);
+		for (i = 4; i < cnt; i++) {
+			snprintf(lbuf, sizeof(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-7/src/appl/telnet/libtelnet/key-proto.h b/krb5-1-7/src/appl/telnet/libtelnet/key-proto.h
new file mode 100644
index 000000000..0a19c97bc
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/krb5forw.h b/krb5-1-7/src/appl/telnet/libtelnet/krb5forw.h
new file mode 100644
index 000000000..1fb757ddf
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/mem.c b/krb5-1-7/src/appl/telnet/libtelnet/mem.c
new file mode 100644
index 000000000..5a2ced8d5
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/misc-proto.h b/krb5-1-7/src/appl/telnet/libtelnet/misc-proto.h
new file mode 100644
index 000000000..66e9dd7bf
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/misc.c b/krb5-1-7/src/appl/telnet/libtelnet/misc.c
new file mode 100644
index 000000000..86e14cb1b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/misc.h b/krb5-1-7/src/appl/telnet/libtelnet/misc.h
new file mode 100644
index 000000000..8ae603836
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/parsetos.c b/krb5-1-7/src/appl/telnet/libtelnet/parsetos.c
new file mode 100644
index 000000000..303d7c3e5
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/setenv.c b/krb5-1-7/src/appl/telnet/libtelnet/setenv.c
new file mode 100644
index 000000000..941b816ca
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/setsid.c b/krb5-1-7/src/appl/telnet/libtelnet/setsid.c
new file mode 100644
index 000000000..48c861c8c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/spx.c b/krb5-1-7/src/appl/telnet/libtelnet/spx.c
new file mode 100644
index 000000000..449ddc4f7
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/libtelnet/spx.c
@@ -0,0 +1,592 @@
+/*-
+ * 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"
+#include "k5-platform.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));
+		snprintf(targ_printable, sizeof(targ_printable),
+			 "SERVICE:rcmd@%s", lhostname);
+		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");
+	snprintf(targ_printable, sizeof(targ_printable), "SERVICE:rcmd@%s",
+		 RemoteHostName);
+
+	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));
+
+		snprintf(targ_printable, sizeof(targ_printable),
+			 "SERVICE:rcmd@%s", lhostname);
+
+		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:
+		snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[3]);
+		strncpy((char *)buf, lbuf, buflen);
+	common2:
+		BUMP(buf, buflen);
+		for (i = 4; i < cnt; i++) {
+			snprintf(lbuf, sizeof(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-7/src/appl/telnet/libtelnet/strcasecmp.c b/krb5-1-7/src/appl/telnet/libtelnet/strcasecmp.c
new file mode 100644
index 000000000..edd9f1415
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/strchr.c b/krb5-1-7/src/appl/telnet/libtelnet/strchr.c
new file mode 100644
index 000000000..91f5612fa
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/strdup.c b/krb5-1-7/src/appl/telnet/libtelnet/strdup.c
new file mode 100644
index 000000000..d501ed992
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/strerror.c b/krb5-1-7/src/appl/telnet/libtelnet/strerror.c
new file mode 100644
index 000000000..8bed9c670
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/strftime.c b/krb5-1-7/src/appl/telnet/libtelnet/strftime.c
new file mode 100644
index 000000000..f2bcc676c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/libtelnet/strrchr.c b/krb5-1-7/src/appl/telnet/libtelnet/strrchr.c
new file mode 100644
index 000000000..f65a7e805
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/stty.diff b/krb5-1-7/src/appl/telnet/stty.diff
new file mode 100644
index 000000000..3c1b02acc
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet.state b/krb5-1-7/src/appl/telnet/telnet.state
new file mode 100644
index 000000000..1927a2b4b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/Makefile.in b/krb5-1-7/src/appl/telnet/telnet/Makefile.in
new file mode 100644
index 000000000..7fae8f7c5
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/Makefile.in
@@ -0,0 +1,74 @@
+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) $(KRB5_BASE_DEPLIBS) ../libtelnet/libtelnet.a
+	$(CC_LINK) -o $@ $(OBJS) ../libtelnet/libtelnet.a $(KRB5_BASE_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)
diff --git a/krb5-1-7/src/appl/telnet/telnet/authenc.c b/krb5-1-7/src/appl/telnet/telnet/authenc.c
new file mode 100644
index 000000000..aa4459f27
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/commands.c b/krb5-1-7/src/appl/telnet/telnet/commands.c
new file mode 100644
index 000000000..f82f3e680
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/commands.c
@@ -0,0 +1,3189 @@
+/*
+ * 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>
+#include <stdarg.h>
+#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"
+
+#include <k5-platform.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;
+	char **epp, *cp;
+	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';
+		asprintf(&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) strlcpy(line, "open ", sizeof(line));
+	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));
+	    strlcpy (hostaddrstring, "[address unprintable]",
+		     sizeof(hostaddrstring));
+	}
+	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-7/src/appl/telnet/telnet/defines.h b/krb5-1-7/src/appl/telnet/telnet/defines.h
new file mode 100644
index 000000000..0978173ea
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/deps b/krb5-1-7/src/appl/telnet/telnet/deps
new file mode 100644
index 000000000..401547983
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/deps
@@ -0,0 +1,39 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(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): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.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 \
+  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): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(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-7/src/appl/telnet/telnet/externs.h b/krb5-1-7/src/appl/telnet/telnet/externs.h
new file mode 100644
index 000000000..3d098adff
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/fdset.h b/krb5-1-7/src/appl/telnet/telnet/fdset.h
new file mode 100644
index 000000000..045bb7221
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/general.h b/krb5-1-7/src/appl/telnet/telnet/general.h
new file mode 100644
index 000000000..4efa95194
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/main.c b/krb5-1-7/src/appl/telnet/telnet/main.c
new file mode 100644
index 000000000..c1dc2049a
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/main.c
@@ -0,0 +1,341 @@
+/*
+ * 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(KRB5)
+		    {
+			extern char *telnet_krb5_realm;
+
+			telnet_krb5_realm = optarg;
+			break;
+		    }
+#else
+			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-7/src/appl/telnet/telnet/network.c b/krb5-1-7/src/appl/telnet/telnet/network.c
new file mode 100644
index 000000000..60dc3bdcf
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/ring.c b/krb5-1-7/src/appl/telnet/telnet/ring.c
new file mode 100644
index 000000000..fdff682b5
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/ring.h b/krb5-1-7/src/appl/telnet/telnet/ring.h
new file mode 100644
index 000000000..87f0ab77a
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/sys_bsd.c b/krb5-1-7/src/appl/telnet/telnet/sys_bsd.c
new file mode 100644
index 000000000..89f9d4b5a
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/telnet.0.ps b/krb5-1-7/src/appl/telnet/telnet/telnet.0.ps
new file mode 100644
index 000000000..9edd0b321
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/telnet.0.txt b/krb5-1-7/src/appl/telnet/telnet/telnet.0.txt
new file mode 100644
index 000000000..41d410bab
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/telnet.1 b/krb5-1-7/src/appl/telnet/telnet/telnet.1
new file mode 100644
index 000000000..0ed00378b
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/telnet.c b/krb5-1-7/src/appl/telnet/telnet/telnet.c
new file mode 100644
index 000000000..be00687e7
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/telnet.c
@@ -0,0 +1,2760 @@
+/*
+ * 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)  */
+
+#include <k5-platform.h>
+
+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()) {
+		snprintf((char *)temp, sizeof(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);
+
+	    snprintf((char *)temp, sizeof(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;
+	    }
+	    snprintf((char *)temp, sizeof(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-7/src/appl/telnet/telnet/terminal.c b/krb5-1-7/src/appl/telnet/telnet/terminal.c
new file mode 100644
index 000000000..611270373
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/tmac.doc b/krb5-1-7/src/appl/telnet/telnet/tmac.doc
new file mode 100644
index 000000000..464023fea
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/tn3270.c b/krb5-1-7/src/appl/telnet/telnet/tn3270.c
new file mode 100644
index 000000000..c46ae7eb8
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/types.h b/krb5-1-7/src/appl/telnet/telnet/types.h
new file mode 100644
index 000000000..191d311fd
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnet/utilities.c b/krb5-1-7/src/appl/telnet/telnet/utilities.c
new file mode 100644
index 000000000..4a076e530
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnet/utilities.c
@@ -0,0 +1,951 @@
+/*
+ * 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
+
+#include <k5-platform.h>
+
+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];
+		    snprintf(tbuf, sizeof(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-7/src/appl/telnet/telnetd/ISSUES b/krb5-1-7/src/appl/telnet/telnetd/ISSUES
new file mode 100644
index 000000000..5b61997bb
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/Makefile.in b/krb5-1-7/src/appl/telnet/telnetd/Makefile.in
new file mode 100644
index 000000000..ac27b78e5
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/Makefile.in
@@ -0,0 +1,84 @@
+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)
+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) $(KRB5_BASE_DEPLIBS) ../libtelnet/libtelnet.a
+	$(CC_LINK) -o $@ $(OBJS) ../libtelnet/libtelnet.a $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_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)
diff --git a/krb5-1-7/src/appl/telnet/telnetd/authenc.c b/krb5-1-7/src/appl/telnet/telnetd/authenc.c
new file mode 100644
index 000000000..6d8b04ced
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/defs.h b/krb5-1-7/src/appl/telnet/telnetd/defs.h
new file mode 100644
index 000000000..ab653a35f
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/deps b/krb5-1-7/src/appl/telnet/telnetd/deps
new file mode 100644
index 000000000..88e768d39
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/deps
@@ -0,0 +1,58 @@
+# 
+# Generated makefile dependencies follow.
+#
+$(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 \
+  $(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 \
+  $(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 \
+  $(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 \
+  $(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-buf.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/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)/../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 \
+  $(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 \
+  $(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 \
+  $(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-7/src/appl/telnet/telnetd/ext.h b/krb5-1-7/src/appl/telnet/telnetd/ext.h
new file mode 100644
index 000000000..3a0d10320
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/ext.h
@@ -0,0 +1,240 @@
+/*
+ * 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 *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
+extern void netprintf_urg (const char *fmt, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
+extern void netprintf_noflush (const char *fmt, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 1, 2)))
+#endif
+    ;
+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-7/src/appl/telnet/telnetd/global.c b/krb5-1-7/src/appl/telnet/telnetd/global.c
new file mode 100644
index 000000000..c1412834e
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/pathnames.h b/krb5-1-7/src/appl/telnet/telnetd/pathnames.h
new file mode 100644
index 000000000..c8b0806e7
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/slc.c b/krb5-1-7/src/appl/telnet/telnetd/slc.c
new file mode 100644
index 000000000..8f32f433a
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/slc.c
@@ -0,0 +1,492 @@
+/*
+ * 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) snprintf((char *)slcbuf, sizeof(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 {
+			*slcptr++ = IAC;
+			*slcptr++ = SE;
+			*slcptr = 0;
+			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-7/src/appl/telnet/telnetd/state.c b/krb5-1-7/src/appl/telnet/telnetd/state.c
new file mode 100644
index 000000000..4693fc912
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/sys_term.c b/krb5-1-7/src/appl/telnet/telnetd/sys_term.c
new file mode 100644
index 000000000..5c08c7606
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/sys_term.c
@@ -0,0 +1,1494 @@
+/*
+ * 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) snprintf(tbuf, sizeof(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) snprintf(tbuf, sizeof(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;
+		snprintf(tbuf, sizeof(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 {
+			snprintf(termbuf, sizeof(termbuf), "TERM=%s", term);
+			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));
+			snprintf(speed, sizeof(speed), "%s/%d",
+				 (cp = getenv("TERM")) ? cp : "",
+				 (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-7/src/appl/telnet/telnetd/telnetd-ktd.c b/krb5-1-7/src/appl/telnet/telnetd/telnetd-ktd.c
new file mode 100644
index 000000000..295f19580
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/telnetd.0.ps b/krb5-1-7/src/appl/telnet/telnetd/telnetd.0.ps
new file mode 100644
index 000000000..bbbdbd002
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/telnetd.0.txt b/krb5-1-7/src/appl/telnet/telnetd/telnetd.0.txt
new file mode 100644
index 000000000..f13b6994c
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/telnetd.8 b/krb5-1-7/src/appl/telnet/telnetd/telnetd.8
new file mode 100644
index 000000000..78700cbed
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/telnetd.c b/krb5-1-7/src/appl/telnet/telnetd/telnetd.c
new file mode 100644
index 000000000..4115b6671
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/telnetd.c
@@ -0,0 +1,1715 @@
+/*
+ * 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)
+	    snprintf(banner, sizeof(banner),
+		     "\r\nError getting hostname: %s\r\n",
+		     strerror(errno));
+        else {
+#if defined(_AIX)
+	    snprintf(banner, sizeof(banner),
+		     "\r\n    %%h (%s release %s.%s) (%%t)\r\n\r\n",
+		     name.sysname, name.version, name.release);
+#else
+	    snprintf(banner, sizeof(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.*/
+		snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum);
+		if (setdevs(tty_dev, &dv) < 0)
+		 	fatal(net, "cannot set pty security");
+		snprintf(slave_dev, sizeof(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-7/src/appl/telnet/telnetd/telnetd.h b/krb5-1-7/src/appl/telnet/telnetd/telnetd.h
new file mode 100644
index 000000000..f21f617e5
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/termio-tn.c b/krb5-1-7/src/appl/telnet/telnetd/termio-tn.c
new file mode 100644
index 000000000..c34f5eb16
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/termios-tn.c b/krb5-1-7/src/appl/telnet/telnetd/termios-tn.c
new file mode 100644
index 000000000..3e5488371
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/termstat.c b/krb5-1-7/src/appl/telnet/telnetd/termstat.c
new file mode 100644
index 000000000..531e16783
--- /dev/null
+++ b/krb5-1-7/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-7/src/appl/telnet/telnetd/utility.c b/krb5-1-7/src/appl/telnet/telnetd/utility.c
new file mode 100644
index 000000000..4a4c1308e
--- /dev/null
+++ b/krb5-1-7/src/appl/telnet/telnetd/utility.c
@@ -0,0 +1,1303 @@
+/*
+ * 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)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+    __attribute__((__format__(__printf__, 3, 0)))
+#endif
+    ;
+
+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 */
+
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+
+	/*
+	 * 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) snprintf(buf, sizeof(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) snprintf(buf, sizeof(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-7/src/appl/user_user/Makefile.in b/krb5-1-7/src/appl/user_user/Makefile.in
new file mode 100644
index 000000000..b321cc5d1
--- /dev/null
+++ b/krb5-1-7/src/appl/user_user/Makefile.in
@@ -0,0 +1,25 @@
+thisconfigdir=../..
+myfulldir=appl/user_user
+mydir=appl/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-7/src/appl/user_user/client.c b/krb5-1-7/src/appl/user_user/client.c
new file mode 100644
index 000000000..1ee160659
--- /dev/null
+++ b/krb5-1-7/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 "k5-int.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-7/src/appl/user_user/deps b/krb5-1-7/src/appl/user_user/deps
new file mode 100644
index 000000000..2feac3c9d
--- /dev/null
+++ b/krb5-1-7/src/appl/user_user/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/krb5-1-7/src/appl/user_user/server.c b/krb5-1-7/src/appl/user_user/server.c
new file mode 100644
index 000000000..9d1ab19ae
--- /dev/null
+++ b/krb5-1-7/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 "k5-int.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-7/src/ccapi/Makefile.in b/krb5-1-7/src/ccapi/Makefile.in
new file mode 100644
index 000000000..78e2a47fd
--- /dev/null
+++ b/krb5-1-7/src/ccapi/Makefile.in
@@ -0,0 +1,37 @@
+thisconfigdir=..
+myfulldir=ccapi
+mydir=ccapi
+BUILDTOP=$(REL)..
+
+SUBDIRS= lib server test
+
+all-windows:: 
+	@echo Making in ccapi\lib\win
+    @echo buildtop: $(BUILDTOP)
+	cd lib\win
+	cd
+	$(MAKE) -$(MFLAGS)
+	@echo Making in ccapi\server\win
+	cd ..\..\server\win
+	cd
+	$(MAKE) -$(MFLAGS)
+	@echo Making in ccapi\test
+	cd ..\..\test
+	cd
+	$(MAKE) -$(MFLAGS)
+
+clean-windows:: 
+	@echo Making clean in ccapi\lib\win
+	cd lib\win
+	cd
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in ccapi\server\win
+	cd ..\..\server\win
+	cd
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in ccapi\test
+	cd ..\..\test
+	cd
+	$(MAKE) -$(MFLAGS) clean
+
+# +++ Dependency line eater +++
diff --git a/krb5-1-7/src/ccapi/common/Makefile.in b/krb5-1-7/src/ccapi/common/Makefile.in
new file mode 100644
index 000000000..cc5d5c09c
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/Makefile.in
@@ -0,0 +1,67 @@
+thisconfigdir=../..
+myfulldir=ccapi/common
+mydir=ccapi/common
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=unix
+
+SRCS= \
+	cci_array_internal.c \
+	cci_cred_union.c \
+	cci_debugging.c \
+	cci_identifier.c \
+	cci_message.c \
+	cci_stream.c
+
+STLIBOBJS= \
+	cci_array_internal.o \
+	cci_cred_union.o \
+	cci_debugging.o \
+	cci_identifier.o \
+	cci_message.o \
+	cci_stream.o
+
+OBJS= \
+	$(OUTPRE)cci_array_internal.$(OBJEXT) \
+	$(OUTPRE)cci_cred_union.$(OBJEXT) \
+	$(OUTPRE)cci_debugging.$(OBJEXT) \
+	$(OUTPRE)cci_identifier.$(OBJEXT) \
+	$(OUTPRE)cci_message.$(OBJEXT) \
+	$(OUTPRE)cci_stream.$(OBJEXT)
+
+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
+#
+cci_array_internal.so cci_array_internal.po $(OUTPRE)cci_array_internal.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_array_internal.c cci_array_internal.h cci_common.h \
+  cci_cred_union.h cci_debugging.h cci_identifier.h cci_message.h \
+  cci_stream.h cci_types.h
+cci_cred_union.so cci_cred_union.po $(OUTPRE)cci_cred_union.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_common.h cci_cred_union.c cci_cred_union.h cci_debugging.h \
+  cci_identifier.h cci_message.h cci_stream.h cci_types.h
+cci_debugging.so cci_debugging.po $(OUTPRE)cci_debugging.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_common.h cci_cred_union.h cci_debugging.c cci_debugging.h \
+  cci_identifier.h cci_message.h cci_os_debugging.h cci_stream.h \
+  cci_types.h
+cci_identifier.so cci_identifier.po $(OUTPRE)cci_identifier.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.c \
+  cci_identifier.h cci_message.h cci_os_identifier.h \
+  cci_stream.h cci_types.h
+cci_message.so cci_message.po $(OUTPRE)cci_message.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \
+  cci_message.c cci_message.h cci_stream.h cci_types.h
+cci_stream.so cci_stream.po $(OUTPRE)cci_stream.$(OBJEXT): \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/CredentialsCache.h \
+  cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \
+  cci_message.h cci_stream.c cci_stream.h cci_types.h
diff --git a/krb5-1-7/src/ccapi/common/cci_array_internal.c b/krb5-1-7/src/ccapi/common/cci_array_internal.c
new file mode 100644
index 000000000..b5a0f693b
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_array_internal.c
@@ -0,0 +1,314 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006, 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 "cci_common.h"
+#include "cci_array_internal.h"
+
+#ifdef WIN32
+#include "k5-platform.h"
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_array_d {
+    cci_array_object_t *objects;
+    cc_uint64 count;
+    cc_uint64 max_count;
+    
+    cci_array_object_release_t object_release;
+};
+
+struct cci_array_d cci_array_initializer = { NULL, 0, 0, NULL };
+
+#define CCI_ARRAY_COUNT_INCREMENT 16
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_array_resize (cci_array_t io_array,
+                                  cc_uint64   in_new_count)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 new_max_count = 0;
+    
+    if (!io_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint64 old_max_count = io_array->max_count;
+        new_max_count = io_array->max_count;
+        
+        if (in_new_count > old_max_count) {
+            /* Expand the array */
+            while (in_new_count > new_max_count) {
+                new_max_count += CCI_ARRAY_COUNT_INCREMENT;
+            }
+            
+        } else if ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < old_max_count) {
+            /* Shrink the array, but never drop below CC_ARRAY_COUNT_INCREMENT */
+            while ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < new_max_count &&
+                   (new_max_count > CCI_ARRAY_COUNT_INCREMENT)) {
+                new_max_count -= CCI_ARRAY_COUNT_INCREMENT;
+            }
+        }
+    }
+    
+    if (!err && io_array->max_count != new_max_count) {
+        cci_array_object_t *objects = io_array->objects;
+        
+        if (!objects) {
+            objects = malloc (new_max_count * sizeof (*objects));
+        } else {
+            objects = realloc (objects, new_max_count * sizeof (*objects));
+        }
+        if (!objects) { err = cci_check_error (ccErrNoMem); }
+        
+        if (!err) {
+            io_array->objects = objects;
+            io_array->max_count = new_max_count;
+        }        
+    }
+    
+    return cci_check_error (err); 
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_new (cci_array_t                *out_array,
+                        cci_array_object_release_t  in_array_object_release)
+{
+    cc_int32 err = ccNoError;
+    cci_array_t array = NULL;
+    
+    if (!out_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        array = malloc (sizeof (*array));
+        if (array) { 
+            *array = cci_array_initializer;
+            array->object_release = in_array_object_release;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        *out_array = array;
+        array = NULL;
+    }
+    
+    cci_array_release (array);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_release (cci_array_t io_array)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!err && io_array) {
+        cc_uint64 i;
+        
+        if (io_array->object_release) {
+	    for (i = 0; i < io_array->count; i++) {
+		io_array->object_release (io_array->objects[i]);
+	    }
+	}
+        free (io_array->objects);
+        free (io_array);
+    }
+    
+    return err;        
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 cci_array_count (cci_array_t in_array)
+{
+    return in_array ? in_array->count : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+                                              cc_uint64   in_position)
+{
+    if (io_array && in_position < io_array->count) {
+        return io_array->objects[in_position];
+    } else {
+        if (!io_array) {
+            cci_debug_printf ("%s() got NULL array", __FUNCTION__);
+        } else {
+            cci_debug_printf ("%s() got bad index %lld (count = %lld)", __FUNCTION__, 
+                              in_position, io_array->count);
+        }     
+        return NULL;
+    }
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+    
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_insert (cci_array_t        io_array,
+                           cci_array_object_t in_object,
+                           cc_uint64          in_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_object) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Don't try to insert past the end and don't overflow the array */
+        if (in_position > io_array->count || io_array->count == UINT64_MAX) {
+            err = cci_check_error (ccErrBadParam);
+        }
+    }
+    
+    if (!err) {
+        err = cci_array_resize (io_array, io_array->count + 1);
+    }
+    
+    if (!err) {
+        cc_uint64 move_count = io_array->count - in_position;
+        
+        if (move_count > 0) {
+            memmove (&io_array->objects[in_position + 1], &io_array->objects[in_position],
+                     move_count * sizeof (*io_array->objects));
+        }
+        
+        io_array->objects[in_position] = in_object;
+        io_array->count++;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+                           cc_uint64   in_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_position >= io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    
+    if (!err) {
+        cc_uint64 move_count = io_array->count - in_position - 1;
+        cci_array_object_t object = io_array->objects[in_position];
+        
+        if (move_count > 0) {
+            memmove (&io_array->objects[in_position], &io_array->objects[in_position + 1],
+                     move_count * sizeof (*io_array->objects));
+        }
+        io_array->count--;
+        
+        if (io_array->object_release) { io_array->object_release (object); }
+        
+        cci_array_resize (io_array, io_array->count);
+     }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_move (cci_array_t  io_array,
+                         cc_uint64    in_position,
+                         cc_uint64    in_new_position,
+                         cc_uint64   *out_real_new_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array             ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_real_new_position) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_position >= io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    
+    if (!err && in_new_position > io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    if (!err) {
+        cc_uint64 move_from = 0;
+        cc_uint64 move_to = 0;
+        cc_uint64 move_count = 0;
+        cc_uint64 real_new_position = 0;
+        
+        if (in_position < in_new_position) {
+            /* shift right, making an empty space so the
+             * actual new position is one less in_new_position */
+            move_from = in_position + 1;
+            move_to = in_position;
+            move_count = in_new_position - in_position - 1;
+            real_new_position = in_new_position - 1;
+	    
+        } else if (in_position > in_new_position) {
+            /* shift left */
+            move_from = in_new_position;
+            move_to = in_new_position + 1;
+            move_count = in_position - in_new_position;     
+            real_new_position = in_new_position;
+            
+        } else {
+            real_new_position = in_new_position;
+        }
+        
+        if (move_count > 0) {
+            cci_array_object_t object = io_array->objects[in_position];
+            
+            memmove (&io_array->objects[move_to], &io_array->objects[move_from], 
+                     move_count * sizeof (*io_array->objects));
+            io_array->objects[real_new_position] = object;
+        }
+        
+        *out_real_new_position = real_new_position;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+                               cc_uint64   in_position)
+{
+    cc_uint64 real_new_position = 0;
+    return cci_array_move (io_array, in_position, 0, &real_new_position);
+}
+
diff --git a/krb5-1-7/src/ccapi/common/cci_array_internal.h b/krb5-1-7/src/ccapi/common/cci_array_internal.h
new file mode 100644
index 000000000..af7c24bc6
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_array_internal.h
@@ -0,0 +1,66 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_ARRAY_INTERNAL_H
+#define CCI_ARRAY_INTERNAL_H
+
+#include "cci_types.h"
+
+struct cci_array_object_d;
+typedef struct cci_array_object_d *cci_array_object_t;
+
+typedef cc_int32 (*cci_array_object_release_t) (cci_array_object_t);
+
+struct cci_array_d;
+typedef struct cci_array_d *cci_array_t;
+
+cc_int32 cci_array_new (cci_array_t                *out_array,
+                        cci_array_object_release_t  in_array_object_release);
+
+cc_int32 cci_array_release (cci_array_t io_array);
+
+cc_uint64 cci_array_count (cci_array_t in_array);
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+                                              cc_uint64   in_position);
+
+cc_int32 cci_array_insert (cci_array_t        io_array,
+                           cci_array_object_t in_object,
+                           cc_uint64          in_position);
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+                           cc_uint64   in_position);
+
+cc_int32 cci_array_move (cci_array_t  io_array,
+                         cc_uint64    in_position,
+                         cc_uint64    in_new_position,
+                         cc_uint64   *out_real_new_position);
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+                               cc_uint64   in_position);
+
+
+#endif /* CCI_ARRAY_INTERNAL_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_common.h b/krb5-1-7/src/ccapi/common/cci_common.h
new file mode 100644
index 000000000..c1a5d0864
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_common.h
@@ -0,0 +1,57 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006, 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 CCI_COMMON_H
+#define CCI_COMMON_H
+
+#include <CredentialsCache.h>
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <com_err.h>
+
+#if TARGET_OS_MAC
+#include <unistd.h>
+#define VECTOR_FUNCTIONS_INITIALIZER ,NULL
+#else
+#include "win-mac.h"
+#define VECTOR_FUNCTIONS_INITIALIZER
+#endif
+
+#define k_cci_context_initial_ccache_name "Initial default ccache"
+
+#include "cci_cred_union.h"
+#include "cci_debugging.h"
+#include "cci_identifier.h"
+#include "cci_message.h"
+
+#include "k5-ipc_stream.h"
+
+#endif /* CCI_COMMON_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_cred_union.c b/krb5-1-7/src/ccapi/common/cci_cred_union.c
new file mode 100644
index 000000000..9740ffd47
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_cred_union.c
@@ -0,0 +1,1115 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#include "cci_common.h"
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_release (cc_credentials_v4_t *io_v4creds)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_v4creds) { err = ccErrBadParam; }
+    
+    if (!err) {
+        memset (io_v4creds, 0, sizeof (*io_v4creds));
+        free (io_v4creds);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_read (cc_credentials_v4_t **out_v4creds,
+                                          k5_ipc_stream          io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_v4_t *v4creds = NULL;
+    
+    if (!io_stream  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_v4creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        v4creds = malloc (sizeof (*v4creds));
+        if (!v4creds) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &v4creds->version);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->principal, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->principal_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->service, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->service_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->realm, cc_v4_realm_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->session_key, cc_v4_key_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (io_stream, &v4creds->kvno);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (io_stream, &v4creds->string_to_key_type);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_time (io_stream, &v4creds->issue_date);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (io_stream, &v4creds->lifetime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &v4creds->address);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (io_stream, &v4creds->ticket_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, v4creds->ticket, cc_v4_ticket_size);
+    }
+    
+    if (!err) {
+        *out_v4creds = v4creds;
+        v4creds = NULL;
+    }
+    
+    free (v4creds);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_write (cc_credentials_v4_t *in_v4creds,
+                                           k5_ipc_stream         io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_v4creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_v4creds->version);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->principal, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->principal_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->service, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->service_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->realm, cc_v4_realm_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->session_key, cc_v4_key_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (io_stream, in_v4creds->kvno);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (io_stream, in_v4creds->string_to_key_type);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_time (io_stream, in_v4creds->issue_date);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (io_stream, in_v4creds->lifetime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_v4creds->address);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (io_stream, in_v4creds->ticket_size);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_v4creds->ticket, cc_v4_ticket_size);
+    }
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; }
+    
+    if (!err) {
+        if (io_ccdata->length) {
+            memset (io_ccdata->data, 0, io_ccdata->length);
+        }
+        free (io_ccdata->data);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_release (cc_data *io_ccdata)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_cc_data_contents_release (io_ccdata);
+        free (io_ccdata);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_read (cc_data      *io_ccdata,
+                                   k5_ipc_stream io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 type = 0;
+    cc_uint32 length = 0;
+    char *data = NULL;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &type);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &length);
+    }
+    
+    if (!err && length > 0) {
+        data = malloc (length);
+        if (!data) { err = cci_check_error (ccErrNoMem); }
+
+        if (!err) {
+            err = k5_ipc_stream_read (io_stream, data, length);
+        }
+    }
+    
+    if (!err) {
+        io_ccdata->type = type;
+        io_ccdata->length = length;
+        io_ccdata->data = data;
+        data = NULL;
+    }
+    
+    free (data);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_write (cc_data      *in_ccdata,
+                                    k5_ipc_stream io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_ccdata->type);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_ccdata->length);
+    }
+    
+    if (!err && in_ccdata->length > 0) {
+        err = k5_ipc_stream_write (io_stream, in_ccdata->data, in_ccdata->length);
+    }
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata_array) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cc_uint32 i;
+        
+        for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) {
+            cci_cc_data_release (io_ccdata_array[i]);
+        }
+        free (io_ccdata_array);        
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_read (cc_data      ***io_ccdata_array,
+                                         k5_ipc_stream    io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 count = 0;
+    cc_data **array = NULL;
+    cc_uint32 i;
+    
+    if (!io_stream      ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &count);
+    }
+    
+    if (!err && count > 0) {
+        array = malloc ((count + 1) * sizeof (*array));
+        if (array) { 
+            for (i = 0; i <= count; i++) { array[i] = NULL; }
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        for (i = 0; !err && i < count; i++) {
+            array[i] = malloc (sizeof (cc_data));
+            if (!array[i]) { err = cci_check_error (ccErrNoMem); }
+            
+            if (!err) {
+                err = cci_cc_data_read (array[i], io_stream);
+            }
+        }
+    }
+    
+    if (!err) {
+        *io_ccdata_array = array;
+        array = NULL;
+    }
+    
+    cci_cc_data_array_release (array);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_write (cc_data      **in_ccdata_array,
+                                          k5_ipc_stream   io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 count = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    /* in_ccdata_array may be NULL */
+    
+    if (!err) {
+        for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
+        
+        err = k5_ipc_stream_write_uint32 (io_stream, count);
+    }
+    
+    if (!err) {
+        cc_uint32 i;
+        
+        for (i = 0; !err && i < count; i++) {
+            err = cci_cc_data_write (in_ccdata_array[i], io_stream);
+        }            
+    }
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_credentials_v5_t cci_credentials_v5_initializer = {
+    NULL,
+    NULL,
+    { 0, 0, NULL },
+    0, 0, 0, 0, 0, 0, 
+    NULL,
+    { 0, 0, NULL },
+    { 0, 0, NULL },
+    NULL
+};
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_v5creds) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free (io_v5creds->client);
+        free (io_v5creds->server);
+        cci_cc_data_contents_release (&io_v5creds->keyblock);
+        cci_cc_data_array_release (io_v5creds->addresses);
+        cci_cc_data_contents_release (&io_v5creds->ticket);
+        cci_cc_data_contents_release (&io_v5creds->second_ticket);
+        cci_cc_data_array_release (io_v5creds->authdata);
+        free (io_v5creds);        
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds,
+                                          k5_ipc_stream          io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_v5_t *v5creds = NULL;
+    
+    if (!io_stream  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_v5creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        v5creds = malloc (sizeof (*v5creds));
+        if (v5creds) { 
+            *v5creds = cci_credentials_v5_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (io_stream, &v5creds->client);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (io_stream, &v5creds->server);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->keyblock, io_stream);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_time (io_stream, &v5creds->authtime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_time (io_stream, &v5creds->starttime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_time (io_stream, &v5creds->endtime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_time (io_stream, &v5creds->renew_till);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &v5creds->is_skey);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &v5creds->ticket_flags);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_read (&v5creds->addresses, io_stream);
+    }
+        
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->second_ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_read (&v5creds->authdata, io_stream);
+    }
+    
+    if (!err) {
+        *out_v5creds = v5creds;
+        v5creds = NULL;
+    }
+    
+    cci_credentials_v5_release (v5creds);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds,
+                                           k5_ipc_stream         io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_v5creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_string (io_stream, in_v5creds->client);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_string (io_stream, in_v5creds->server);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->keyblock, io_stream);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_time (io_stream, in_v5creds->authtime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_time (io_stream, in_v5creds->starttime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_time (io_stream, in_v5creds->endtime);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_time (io_stream, in_v5creds->renew_till);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_v5creds->is_skey);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_v5creds->ticket_flags);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_write (in_v5creds->addresses, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_write (in_v5creds->authdata, io_stream);
+    }
+    
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_release (cc_credentials_union *io_cred_union)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cred_union) { err = ccErrBadParam; }
+    
+    if (!err) {
+        if (io_cred_union->version == cc_credentials_v4) {
+            cci_credentials_v4_release (io_cred_union->credentials.credentials_v4);
+        } else if (io_cred_union->version == cc_credentials_v5) {
+            cci_credentials_v5_release (io_cred_union->credentials.credentials_v5);
+        }
+        free (io_cred_union);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union,
+                                      k5_ipc_stream           io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_union *credentials_union = NULL;
+    
+    if (!io_stream            ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        credentials_union = calloc (1, sizeof (*credentials_union));
+        if (!credentials_union) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &credentials_union->version);
+    }
+    
+    if (!err) {
+        if (credentials_union->version == cc_credentials_v4) {
+            err = cci_credentials_v4_read (&credentials_union->credentials.credentials_v4,
+                                           io_stream);
+        
+        } else if (credentials_union->version == cc_credentials_v5) {
+            err = cci_credentials_v5_read (&credentials_union->credentials.credentials_v5,
+                                           io_stream);
+           
+        
+        } else {
+            err = ccErrBadCredentialsVersion;
+        }
+    }
+    
+    if (!err) {
+        *out_credentials_union = credentials_union;
+        credentials_union = NULL;
+    }
+    
+    if (credentials_union) { cci_credentials_union_release (credentials_union); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union,
+                                       k5_ipc_stream                io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (io_stream, in_credentials_union->version);
+    }
+    
+    if (!err) {
+        if (in_credentials_union->version == cc_credentials_v4) {
+            err = cci_credentials_v4_write (in_credentials_union->credentials.credentials_v4,
+                                            io_stream);
+            
+        } else if (in_credentials_union->version == cc_credentials_v5) {
+            err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5,
+                                            io_stream);
+            
+        } else {
+            err = ccErrBadCredentialsVersion;
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#pragma mark -- CCAPI v2 Compat --
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_credentials_v5_compat cci_credentials_v5_compat_initializer = {
+    NULL,
+    NULL,
+    { 0, 0, NULL },
+    0, 0, 0, 0, 0, 0, 
+    NULL,
+    { 0, 0, NULL },
+    { 0, 0, NULL },
+    NULL
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_release (cred_union *io_cred_union)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cred_union) { err = ccErrBadParam; }
+    
+    if (!err) {
+        if (io_cred_union->cred_type == CC_CRED_V4) {
+            memset (io_cred_union->cred.pV4Cred, 0, sizeof (cc_credentials_v4_compat));
+            free (io_cred_union->cred.pV4Cred);
+            
+        } else if (io_cred_union->cred_type == CC_CRED_V5) {
+            free (io_cred_union->cred.pV5Cred->client);
+            free (io_cred_union->cred.pV5Cred->server);
+            cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->keyblock);
+            cci_cc_data_array_release (io_cred_union->cred.pV5Cred->addresses);
+            cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->ticket);
+            cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->second_ticket);
+            cci_cc_data_array_release (io_cred_union->cred.pV5Cred->authdata);
+            free (io_cred_union->cred.pV5Cred);        
+        }
+        free (io_cred_union);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_copy_contents (cc_data      *io_ccdata,
+                                            cc_data      *in_ccdata)
+{
+    cc_int32 err = ccNoError;
+    char *data = NULL;
+    
+    if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
+    if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_ccdata->length > 0) {
+        data = malloc (in_ccdata->length);
+        if (data) {
+            memcpy (data, in_ccdata->data, in_ccdata->length);
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        io_ccdata->type = in_ccdata->type;
+        io_ccdata->length = in_ccdata->length;
+        io_ccdata->data = data;
+        data = NULL;
+    }
+    
+    free (data);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_copy (cc_data      ***io_ccdata_array,
+                                         cc_data       **in_ccdata_array)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 count = 0;
+    cc_data **array = NULL;
+    cc_uint32 i;
+    
+    if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
+    }
+    
+    if (!err && count > 0) {
+        array = malloc ((count + 1) * sizeof (*array));
+        if (array) { 
+            for (i = 0; i <= count; i++) { array[i] = NULL; }
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        for (i = 0; !err && i < count; i++) {
+            array[i] = malloc (sizeof (cc_data));
+            if (!array[i]) { err = cci_check_error (ccErrNoMem); }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (array[i], in_ccdata_array[i]);
+            }
+        }
+    }
+    
+    if (!err) {
+        *io_ccdata_array = array;
+        array = NULL;
+    }
+    
+    cci_cc_data_array_release (array);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union  *in_credentials_union,
+                                               cred_union                 **out_cred_union)
+{
+    cc_int32 err = ccNoError;
+    cred_union *compat_cred_union = NULL;
+    
+    if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    if (!out_cred_union      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        compat_cred_union = calloc (1, sizeof (*compat_cred_union));
+        if (!compat_cred_union) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        if (in_credentials_union->version == cc_credentials_v4) {
+            cc_credentials_v4_compat *compat_v4creds = NULL;
+            
+            compat_v4creds = malloc (sizeof (*compat_v4creds));
+            if (!compat_v4creds) { err = cci_check_error (ccErrNoMem); }
+            
+            if (!err) {
+                cc_credentials_v4_t *v4creds = in_credentials_union->credentials.credentials_v4;
+                
+                compat_cred_union->cred_type = CC_CRED_V4;
+                compat_cred_union->cred.pV4Cred = compat_v4creds;
+                
+                compat_v4creds->kversion = v4creds->version;
+                strncpy (compat_v4creds->principal,          v4creds->principal,          KRB_NAME_SZ+1);
+                strncpy (compat_v4creds->principal_instance, v4creds->principal_instance, KRB_INSTANCE_SZ+1);
+                strncpy (compat_v4creds->service,            v4creds->service,            KRB_NAME_SZ+1);
+                strncpy (compat_v4creds->service_instance,   v4creds->service_instance,   KRB_INSTANCE_SZ+1);
+                strncpy (compat_v4creds->realm,              v4creds->realm,              KRB_REALM_SZ+1);
+                memcpy (compat_v4creds->session_key, v4creds->session_key, 8);
+                compat_v4creds->kvno       = v4creds->kvno;
+                compat_v4creds->str_to_key = v4creds->string_to_key_type;
+                compat_v4creds->issue_date = v4creds->issue_date;
+                compat_v4creds->lifetime   = v4creds->lifetime;
+                compat_v4creds->address    = v4creds->address;
+                compat_v4creds->ticket_sz  = v4creds->ticket_size;
+                memcpy (compat_v4creds->ticket, v4creds->ticket, MAX_V4_CRED_LEN);
+                compat_v4creds->oops = 0;
+            }
+            
+        } else if (in_credentials_union->version == cc_credentials_v5) {
+            cc_credentials_v5_t *v5creds = in_credentials_union->credentials.credentials_v5;
+            cc_credentials_v5_compat *compat_v5creds = NULL;
+            
+            compat_v5creds = malloc (sizeof (*compat_v5creds));
+            if (compat_v5creds) { 
+                *compat_v5creds = cci_credentials_v5_compat_initializer;
+            } else {
+                err = cci_check_error (ccErrNoMem); 
+            }
+            
+            if (!err) {
+                if (!v5creds->client) { 
+                    err = cci_check_error (ccErrBadParam);
+                } else {
+                    compat_v5creds->client = strdup (v5creds->client);
+                    if (!compat_v5creds->client) { err = cci_check_error (ccErrNoMem); }
+                }
+            }
+            
+            if (!err) {
+                if (!v5creds->server) { 
+                    err = cci_check_error (ccErrBadParam);
+                } else {
+                    compat_v5creds->server = strdup (v5creds->server);
+                    if (!compat_v5creds->server) { err = cci_check_error (ccErrNoMem); }
+                }
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&compat_v5creds->keyblock, &v5creds->keyblock);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_array_copy (&compat_v5creds->addresses, v5creds->addresses);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&compat_v5creds->ticket, &v5creds->ticket);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&compat_v5creds->second_ticket, &v5creds->second_ticket);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_array_copy (&compat_v5creds->authdata, v5creds->authdata);
+            }
+            
+            if (!err) {
+                compat_cred_union->cred_type = CC_CRED_V5;
+                compat_cred_union->cred.pV5Cred = compat_v5creds;
+                
+                compat_v5creds->keyblock      = v5creds->keyblock;
+                compat_v5creds->authtime      = v5creds->authtime;
+                compat_v5creds->starttime     = v5creds->starttime;
+                compat_v5creds->endtime       = v5creds->endtime;
+                compat_v5creds->renew_till    = v5creds->renew_till;
+                compat_v5creds->is_skey       = v5creds->is_skey;
+                compat_v5creds->ticket_flags  = v5creds->ticket_flags;
+            }
+        } else {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    } 
+    
+    if (!err) {
+        *out_cred_union = compat_cred_union;
+        compat_cred_union = NULL;
+    }
+    
+    if (compat_cred_union) { cci_cred_union_release (compat_cred_union); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_to_credentials_union (const cred_union      *in_cred_union,
+                                               cc_credentials_union **out_credentials_union)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_union *creds_union = NULL;
+    
+    if (!in_cred_union        ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        creds_union = calloc (1, sizeof (*creds_union));
+        if (!creds_union) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        if (in_cred_union->cred_type == CC_CRED_V4) {
+            cc_credentials_v4_compat *compat_v4creds = in_cred_union->cred.pV4Cred;
+            cc_credentials_v4_t *v4creds = NULL;
+            
+            if (!err) {
+                v4creds = malloc (sizeof (*v4creds));
+                if (!v4creds) { err = cci_check_error (ccErrNoMem); }
+            }
+            
+            if (!err) {
+                creds_union->version = cc_credentials_v4;
+                creds_union->credentials.credentials_v4 = v4creds;
+                
+                v4creds->version = compat_v4creds->kversion;
+                strncpy (v4creds->principal,          compat_v4creds->principal,          KRB_NAME_SZ);
+                strncpy (v4creds->principal_instance, compat_v4creds->principal_instance, KRB_INSTANCE_SZ);
+                strncpy (v4creds->service,            compat_v4creds->service,            KRB_NAME_SZ);
+                strncpy (v4creds->service_instance,   compat_v4creds->service_instance,   KRB_INSTANCE_SZ);
+                strncpy (v4creds->realm,              compat_v4creds->realm,              KRB_REALM_SZ);
+                memcpy (v4creds->session_key, compat_v4creds->session_key, 8);
+                v4creds->kvno               = compat_v4creds->kvno;
+                v4creds->string_to_key_type = compat_v4creds->str_to_key;
+                v4creds->issue_date         = compat_v4creds->issue_date;
+                v4creds->lifetime           = compat_v4creds->lifetime;
+                v4creds->address            = compat_v4creds->address;
+                v4creds->ticket_size        = compat_v4creds->ticket_sz;
+                memcpy (v4creds->ticket, compat_v4creds->ticket, MAX_V4_CRED_LEN);
+            }
+            
+        } else if (in_cred_union->cred_type == CC_CRED_V5) {
+            cc_credentials_v5_compat *compat_v5creds = in_cred_union->cred.pV5Cred;
+            cc_credentials_v5_t *v5creds = NULL;
+            
+            if (!err) {
+                v5creds = malloc (sizeof (*v5creds));
+                if (v5creds) { 
+                    *v5creds = cci_credentials_v5_initializer;
+                } else {
+                    err = cci_check_error (ccErrNoMem); 
+                }
+            }
+            
+            if (!err) {
+                if (!compat_v5creds->client) { 
+                    err = cci_check_error (ccErrBadParam);
+                } else {
+                    v5creds->client = strdup (compat_v5creds->client);
+                    if (!v5creds->client) { err = cci_check_error (ccErrNoMem); }
+                }
+            }
+            
+            if (!err) {
+                if (!compat_v5creds->server) { 
+                    err = cci_check_error (ccErrBadParam);
+                } else {
+                    v5creds->server = strdup (compat_v5creds->server);
+                    if (!v5creds->server) { err = cci_check_error (ccErrNoMem); }
+                }
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&v5creds->keyblock, &compat_v5creds->keyblock);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_array_copy (&v5creds->addresses, compat_v5creds->addresses);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&v5creds->ticket, &compat_v5creds->ticket);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_copy_contents (&v5creds->second_ticket, &compat_v5creds->second_ticket);
+            }
+            
+            if (!err) {
+                err = cci_cc_data_array_copy (&v5creds->authdata, compat_v5creds->authdata);
+            }
+            
+            if (!err) {
+                creds_union->version = cc_credentials_v5;
+                creds_union->credentials.credentials_v5 = v5creds;
+                
+                v5creds->authtime      = compat_v5creds->authtime;
+                v5creds->starttime     = compat_v5creds->starttime;
+                v5creds->endtime       = compat_v5creds->endtime;
+                v5creds->renew_till    = compat_v5creds->renew_till;
+                v5creds->is_skey       = compat_v5creds->is_skey;
+                v5creds->ticket_flags  = compat_v5creds->ticket_flags;
+            }
+            
+        } else {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    } 
+    
+    if (!err) {
+        *out_credentials_union = creds_union;
+        creds_union = NULL;
+    }
+    
+    if (creds_union) { cci_credentials_union_release (creds_union); }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union           *in_cred_union_compat,
+                                                       const cc_credentials_union *in_credentials_union,
+                                                       cc_uint32                  *out_equal) 
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 equal = 0;
+    
+    if (!in_cred_union_compat) { err = cci_check_error (ccErrBadParam); }
+    if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal           ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (in_cred_union_compat->cred_type == CC_CRED_V4 && 
+            in_credentials_union->version == cc_credentials_v4) {
+            cc_credentials_v4_compat *old_creds_v4 = in_cred_union_compat->cred.pV4Cred;
+            cc_credentials_v4_t *new_creds_v4 = in_credentials_union->credentials.credentials_v4;
+            
+            if (old_creds_v4 && new_creds_v4 &&
+                !strcmp (old_creds_v4->principal, 
+                         new_creds_v4->principal) &&
+                !strcmp (old_creds_v4->principal_instance, 
+                         new_creds_v4->principal_instance) &&
+                !strcmp (old_creds_v4->service, 
+                         new_creds_v4->service) &&
+                !strcmp (old_creds_v4->service_instance, 
+                         new_creds_v4->service_instance) &&
+                !strcmp (old_creds_v4->realm, new_creds_v4->realm) &&
+                (old_creds_v4->issue_date == (long) new_creds_v4->issue_date)) { 
+                equal = 1;
+            }
+            
+        } else if (in_cred_union_compat->cred_type == CC_CRED_V5 && 
+                   in_credentials_union->version == cc_credentials_v5) {
+            cc_credentials_v5_compat *old_creds_v5 = in_cred_union_compat->cred.pV5Cred;
+            cc_credentials_v5_t *new_creds_v5 = in_credentials_union->credentials.credentials_v5;
+            
+            /* Really should use krb5_parse_name and krb5_principal_compare */
+            if (old_creds_v5 && new_creds_v5 &&
+                !strcmp (old_creds_v5->client, new_creds_v5->client) &&
+                !strcmp (old_creds_v5->server, new_creds_v5->server) &&
+                (old_creds_v5->starttime == new_creds_v5->starttime)) { 
+                equal = 1;
+            }
+        }
+    }
+    
+    if (!err) {
+        *out_equal = equal;
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/krb5-1-7/src/ccapi/common/cci_cred_union.h b/krb5-1-7/src/ccapi/common/cci_cred_union.h
new file mode 100644
index 000000000..44dd6348d
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_cred_union.h
@@ -0,0 +1,53 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_CRED_UNION_H
+#define CCI_CRED_UNION_H
+
+#include "cci_types.h"
+#include <CredentialsCache2.h>
+
+cc_uint32 cci_credentials_union_release (cc_credentials_union *io_credentials);
+
+cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union,
+                                      k5_ipc_stream           io_stream);
+
+cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union,
+                                       k5_ipc_stream                io_stream);
+
+cc_uint32 cci_cred_union_release (cred_union *io_cred_union);
+
+cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union  *in_credentials_union,
+                                               cred_union                 **out_cred_union);
+
+cc_uint32 cci_cred_union_to_credentials_union (const cred_union      *in_cred_union,
+                                               cc_credentials_union **out_credentials_union);
+
+cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union           *in_cred_union_compat,
+                                                       const cc_credentials_union *in_credentials_union,
+                                                       cc_uint32                  *out_equal);
+
+#endif /* CCI_CRED_UNION_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_debugging.c b/krb5-1-7/src/ccapi/common/cci_debugging.c
new file mode 100644
index 000000000..4545b402e
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_debugging.c
@@ -0,0 +1,55 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_debugging.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 _cci_check_error (cc_int32    in_error, 
+                           const char *in_function, 
+                           const char *in_file, 
+                           int         in_line)
+{
+    /* Do not log for flow control errors or when there is no error at all */
+    if (in_error != ccNoError && in_error != ccIteratorEnd) {
+        cci_debug_printf ("%s() got %d at %s: %d", in_function, 
+                          in_error, in_file, in_line);
+    }
+    
+    return in_error;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+void cci_debug_printf (const char *in_format, ...)
+{
+    va_list args;
+    
+    va_start (args, in_format);
+    cci_os_debug_vprintf (in_format, args);
+    va_end (args);
+}
diff --git a/krb5-1-7/src/ccapi/common/cci_debugging.h b/krb5-1-7/src/ccapi/common/cci_debugging.h
new file mode 100644
index 000000000..8875e1a03
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_debugging.h
@@ -0,0 +1,44 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_DEBUGGING_H
+#define CCI_DEBUGGING_H
+
+#include "cci_types.h"
+
+cc_int32 _cci_check_error (cc_int32    in_err, 
+                           const char *in_function, 
+                           const char *in_file, 
+                           int         in_line);
+#define cci_check_error(err) _cci_check_error(err, __FUNCTION__, __FILE__, __LINE__)
+
+void cci_debug_printf (const char *in_format, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+__attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+;
+
+#endif /* CCI_DEBUGGING_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_identifier.c b/krb5-1-7/src/ccapi/common/cci_identifier.c
new file mode 100644
index 000000000..5ca962f1c
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_identifier.c
@@ -0,0 +1,291 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006, 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 "cci_common.h"
+#include "cci_os_identifier.h"
+
+struct cci_identifier_d {
+    cci_uuid_string_t server_id;
+    cci_uuid_string_t object_id;
+};
+
+struct cci_identifier_d cci_identifier_initializer = { NULL, NULL };
+
+#define cci_uninitialized_server_id "NEEDS_SYNC"
+#define cci_uninitialized_object_id "NEEDS_SYNC"
+
+struct cci_identifier_d cci_identifier_uninitialized_d = { 
+    cci_uninitialized_server_id, 
+    cci_uninitialized_object_id 
+};
+const cci_identifier_t cci_identifier_uninitialized = &cci_identifier_uninitialized_d;
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+    return cci_os_identifier_new_uuid (out_uuid_string);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_identifier_alloc (cci_identifier_t *out_identifier,
+                                      cci_uuid_string_t in_server_id,
+                                      cci_uuid_string_t in_object_id)
+{
+    cc_int32 err = ccNoError;
+    cci_identifier_t identifier = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_object_id  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        identifier = malloc (sizeof (*identifier));
+        if (identifier) { 
+            *identifier = cci_identifier_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        identifier->server_id = strdup (in_server_id);
+        if (!identifier->server_id) { err = cci_check_error (ccErrNoMem); }        
+    }
+    
+    if (!err) {
+        identifier->object_id = strdup (in_object_id);
+        if (!identifier->object_id) { err = cci_check_error (ccErrNoMem); }        
+    }
+    
+    if (!err) {
+        *out_identifier = identifier;
+        identifier = NULL; /* take ownership */
+    }
+    
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+                             cci_uuid_string_t in_server_id)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t object_id = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_os_identifier_new_uuid (&object_id);
+    }
+    
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, in_server_id, object_id);
+    }
+    
+    if (object_id) { free (object_id); }
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+                              cci_identifier_t  in_identifier)
+{
+    cc_int32 err = ccNoError;
+
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, 
+                                    in_identifier->server_id,
+                                    in_identifier->object_id);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier)
+{
+    cc_int32 err = ccNoError;
+    
+    /* Do not free the static "uninitialized" identifier */
+    if (!err && in_identifier && in_identifier != cci_identifier_uninitialized) {
+        free (in_identifier->server_id);
+        free (in_identifier->object_id);
+        free (in_identifier);
+    }
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare (cci_identifier_t  in_identifier,
+                                 cci_identifier_t  in_compare_to_identifier,
+                                 cc_uint32        *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal               ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal = (!strcmp (in_identifier->object_id, 
+                               in_compare_to_identifier->object_id) &&
+                      !strcmp (in_identifier->server_id, 
+                               in_compare_to_identifier->server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t  in_identifier,
+                                       cci_uuid_string_t in_server_id,
+                                       cc_uint32        *out_is_for_server)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier    ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_for_server) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_for_server = (!strcmp (in_identifier->server_id, in_server_id) ||
+                              !strcmp (in_identifier->server_id, cci_uninitialized_server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t  in_identifier,
+                                           cci_identifier_t  in_compare_to_identifier,
+                                           cc_uint32        *out_equal_server_id)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal_server_id     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal_server_id = (!strcmp (in_identifier->server_id, 
+                                         in_compare_to_identifier->server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t  in_identifier,
+                                        cc_uint32        *out_is_initialized)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_initialized) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_initialized = (strcmp (in_identifier->server_id, 
+                                       cci_uninitialized_server_id) != 0);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+                               k5_ipc_stream      io_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t server_id = NULL;
+    cci_uuid_string_t object_id = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (io_stream, &server_id);
+    }
+
+    if (!err) {
+        err = k5_ipc_stream_read_string (io_stream, &object_id);
+    }    
+     
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, server_id, object_id);
+    }
+    
+    k5_ipc_stream_free_string (server_id);
+    k5_ipc_stream_free_string (object_id);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+                                k5_ipc_stream     io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream    ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_string (io_stream, in_identifier->server_id);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_string (io_stream, in_identifier->object_id);
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/krb5-1-7/src/ccapi/common/cci_identifier.h b/krb5-1-7/src/ccapi/common/cci_identifier.h
new file mode 100644
index 000000000..2c7ea20ab
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_identifier.h
@@ -0,0 +1,65 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_IDENTIFIER_H
+#define CCI_IDENTIFIER_H
+
+#include "cci_types.h"
+
+extern const cci_identifier_t cci_identifier_uninitialized;
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+                             cci_uuid_string_t in_server_id);
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+                              cci_identifier_t  in_handle);
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier);
+
+cc_int32 cci_identifier_compare (cci_identifier_t  in_identifier,
+                                 cci_identifier_t  in_compare_to_identifier,
+                                 cc_uint32        *out_equal);
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t  in_identifier,
+                                       cci_uuid_string_t in_server_id,
+                                       cc_uint32        *out_is_for_server);
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t  in_identifier,
+                                           cci_identifier_t  in_compare_to_identifier,
+                                           cc_uint32        *out_equal_server_id);
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t  in_identifier,
+                                        cc_uint32        *out_is_initialized);
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+                               k5_ipc_stream      io_stream);
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+                                k5_ipc_stream     io_stream);
+
+#endif /* CCI_IDENTIFIER_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_message.c b/krb5-1-7/src/ccapi/common/cci_message.c
new file mode 100644
index 000000000..b54155889
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_message.c
@@ -0,0 +1,214 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#include "cci_common.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name)
+{
+    cc_int32 err = ccNoError;
+    
+    if (in_request_name > cci_context_first_msg_id &&
+        in_request_name < cci_context_last_msg_id) {
+        err = ccErrInvalidContext;
+        
+    } else if (in_request_name > cci_ccache_first_msg_id &&
+               in_request_name < cci_ccache_last_msg_id) {
+        err = ccErrInvalidCCache;
+        
+    } else if (in_request_name > cci_ccache_iterator_first_msg_id &&
+               in_request_name < cci_ccache_iterator_last_msg_id) {
+        err = ccErrInvalidCCacheIterator;
+        
+    } else if (in_request_name > cci_credentials_iterator_first_msg_id &&
+               in_request_name < cci_credentials_iterator_last_msg_id) {
+        err = ccErrInvalidCredentialsIterator;
+        
+    } else {
+        err = ccErrBadInternalMessage;
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_request_header (k5_ipc_stream      *out_request,
+                                         enum cci_msg_id_t  in_request_name,
+                                         cci_identifier_t   in_identifier)
+{
+    cc_int32 err = ccNoError;
+    k5_ipc_stream request = NULL;
+    
+    if (!out_request) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_uint32 (request, in_request_name);
+    }
+    
+    if (!err) {
+        err = cci_identifier_write (in_identifier, request);
+    }
+    
+    if (!err) {
+        *out_request = request;
+        request = NULL;
+    }
+    
+    k5_ipc_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_request_header (k5_ipc_stream       in_request,
+                                          enum cci_msg_id_t *out_request_name,
+                                          cci_identifier_t  *out_identifier)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 request_name;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_request      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_request_name) { err = cci_check_error (ccErrBadParam); }
+    if (!out_identifier  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (in_request, &request_name);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, in_request);
+    }
+    
+    if (!err) {
+        *out_request_name = request_name;
+        *out_identifier = identifier;
+        identifier = NULL; /* take ownership */
+    }
+    
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_reply_header (k5_ipc_stream     *out_reply,
+                                       cc_int32          in_error)
+{
+    cc_int32 err = ccNoError;
+    k5_ipc_stream reply = NULL;
+    
+    if (!out_reply) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_new (&reply);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (reply, in_error);
+    }
+    
+    if (!err) {
+        *out_reply = reply;
+        reply = NULL;
+    }
+    
+    k5_ipc_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_reply_header (k5_ipc_stream      in_reply,
+                                        cc_int32         *out_reply_error)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 reply_err = 0;
+    
+    if (!in_reply       ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_error) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (in_reply, &reply_err);
+    }
+    
+    if (!err) {
+        *out_reply_error = reply_err;
+    }
+    
+    return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_time (k5_ipc_stream  io_stream, 
+                                  cc_time_t     *out_time)
+{
+    int32_t err = 0;
+    int64_t t = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_time ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int64 (io_stream, &t);
+    }
+    
+    if (!err) {
+        *out_time = t;
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, 
+                                   cc_time_t     in_time)
+{
+    int32_t err = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int64 (io_stream, in_time);
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/krb5-1-7/src/ccapi/common/cci_message.h b/krb5-1-7/src/ccapi/common/cci_message.h
new file mode 100644
index 000000000..27ed9c1f2
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_message.h
@@ -0,0 +1,53 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_MESSAGE_H
+#define CCI_MESSAGE_H
+
+#include "cci_types.h"
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name);
+
+cc_int32 cci_message_new_request_header (k5_ipc_stream     *out_request,
+                                         enum cci_msg_id_t in_request_name,
+                                         cci_identifier_t  in_identifier);
+
+cc_int32 cci_message_read_request_header (k5_ipc_stream       in_request,
+                                          enum cci_msg_id_t *out_request_name,
+                                          cci_identifier_t  *out_identifier);
+
+cc_int32 cci_message_new_reply_header (k5_ipc_stream     *out_reply,
+                                       cc_int32          in_error);
+
+cc_int32 cci_message_read_reply_header (k5_ipc_stream in_reply,
+                                        cc_int32     *out_reply_error);
+
+uint32_t k5_ipc_stream_read_time (k5_ipc_stream  io_stream, 
+                               cc_time_t     *out_time);
+uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, 
+                                cc_time_t     in_time);
+
+#endif /* CCI_MESSAGE_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_os_debugging.h b/krb5-1-7/src/ccapi/common/cci_os_debugging.h
new file mode 100644
index 000000000..b2a74e129
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_os_debugging.h
@@ -0,0 +1,35 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_OS_DEBUGGING_H
+#define CCI_OS_DEBUGGING_H
+
+#include "cci_types.h"
+#include <stdarg.h>
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args);
+
+#endif /* CCI_OS_DEBUGGING_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_os_identifier.h b/krb5-1-7/src/ccapi/common/cci_os_identifier.h
new file mode 100644
index 000000000..3112902f0
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_os_identifier.h
@@ -0,0 +1,34 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_OS_IDENTIFIER_H
+#define CCI_OS_IDENTIFIER_H
+
+#include "cci_types.h"
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+#endif /* CCI_OS_IDENTIFIER_H */
diff --git a/krb5-1-7/src/ccapi/common/cci_types.h b/krb5-1-7/src/ccapi/common/cci_types.h
new file mode 100644
index 000000000..43f7100ce
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/cci_types.h
@@ -0,0 +1,103 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#ifndef CCI_TYPES_H
+#define CCI_TYPES_H
+
+#include <CredentialsCache.h>
+#include <k5-ipc_stream.h>
+
+typedef char *cci_uuid_string_t;
+
+struct cci_identifier_d;
+typedef struct cci_identifier_d *cci_identifier_t;
+
+enum cci_msg_id_t {
+    /* cc_context_t */
+    cci_context_first_msg_id,
+    
+    cci_context_unused_release_msg_id,  /* Unused. Handle for old clients. */
+    cci_context_sync_msg_id,
+    cci_context_get_change_time_msg_id,
+    cci_context_wait_for_change_msg_id,
+    cci_context_get_default_ccache_name_msg_id,
+    cci_context_open_ccache_msg_id,
+    cci_context_open_default_ccache_msg_id,
+    cci_context_create_ccache_msg_id,
+    cci_context_create_default_ccache_msg_id,
+    cci_context_create_new_ccache_msg_id,
+    cci_context_new_ccache_iterator_msg_id,
+    cci_context_lock_msg_id,
+    cci_context_unlock_msg_id,
+    
+    cci_context_last_msg_id,
+    
+    /* cc_ccache_t */
+    cci_ccache_first_msg_id,
+    
+    cci_ccache_destroy_msg_id,
+    cci_ccache_set_default_msg_id,
+    cci_ccache_get_credentials_version_msg_id,
+    cci_ccache_get_name_msg_id,
+    cci_ccache_get_principal_msg_id,
+    cci_ccache_set_principal_msg_id,
+    cci_ccache_store_credentials_msg_id,
+    cci_ccache_remove_credentials_msg_id,
+    cci_ccache_new_credentials_iterator_msg_id,
+    cci_ccache_move_msg_id,
+    cci_ccache_lock_msg_id,
+    cci_ccache_unlock_msg_id,
+    cci_ccache_get_last_default_time_msg_id,
+    cci_ccache_get_change_time_msg_id,
+    cci_ccache_wait_for_change_msg_id,
+    cci_ccache_get_kdc_time_offset_msg_id,
+    cci_ccache_set_kdc_time_offset_msg_id,
+    cci_ccache_clear_kdc_time_offset_msg_id,
+    
+    cci_ccache_last_msg_id,
+    
+    /* cc_ccache_iterator_t */
+    cci_ccache_iterator_first_msg_id,
+    
+    cci_ccache_iterator_release_msg_id,
+    cci_ccache_iterator_next_msg_id,
+    cci_ccache_iterator_clone_msg_id,
+    
+    cci_ccache_iterator_last_msg_id,
+    
+    /* cc_credentials_iterator_t */
+    cci_credentials_iterator_first_msg_id,
+    
+    cci_credentials_iterator_release_msg_id,
+    cci_credentials_iterator_next_msg_id,
+    cci_credentials_iterator_clone_msg_id,
+    
+    cci_credentials_iterator_last_msg_id,
+    
+    cci_max_msg_id  /* must be last! */
+};                              
+
+#endif /* CCI_TYPES_H */
diff --git a/krb5-1-7/src/ccapi/common/mac/cci_os_debugging.c b/krb5-1-7/src/ccapi/common/mac/cci_os_debugging.c
new file mode 100644
index 000000000..02f06324c
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/mac/cci_os_debugging.c
@@ -0,0 +1,36 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+
+#include "cci_os_debugging.h"
+#include <Kerberos/KerberosDebug.h>
+
+/* ------------------------------------------------------------------------ */
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args)
+{
+    dvprintf (in_format, in_args);
+}
diff --git a/krb5-1-7/src/ccapi/common/mac/cci_os_identifier.c b/krb5-1-7/src/ccapi/common/mac/cci_os_identifier.c
new file mode 100644
index 000000000..5f3d0651a
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/mac/cci_os_identifier.c
@@ -0,0 +1,80 @@
+/*
+ * $Header$
+ *
+ * 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t uuid_string = NULL;
+    CFUUIDRef uuid = NULL;
+    CFStringRef uuid_stringref = NULL;
+    CFStringEncoding encoding = kCFStringEncodingUTF8;
+    CFIndex length = 0;
+    
+    if (!out_uuid_string) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        uuid = CFUUIDCreate (kCFAllocatorDefault);
+        if (!uuid) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        uuid_stringref = CFUUIDCreateString (kCFAllocatorDefault, uuid); 
+        if (!uuid_stringref) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (uuid_stringref), 
+                                                    encoding) + 1;
+        
+        uuid_string = malloc (length);
+        if (!uuid_string) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        if (!CFStringGetCString (uuid_stringref, uuid_string, length, encoding)) {
+            err = cci_check_error (ccErrNoMem);
+        }        
+    }
+    
+    if (!err) {
+        *out_uuid_string = uuid_string;
+        uuid_string = NULL; /* take ownership */
+    }
+    
+    if (uuid_string   ) { free (uuid_string); }
+    if (uuid_stringref) { CFRelease (uuid_stringref); }
+    if (uuid          ) { CFRelease (uuid); }
+    
+    return cci_check_error (err);
+}
+
diff --git a/krb5-1-7/src/ccapi/common/unix/Makefile.in b/krb5-1-7/src/ccapi/common/unix/Makefile.in
new file mode 100644
index 000000000..1c2acebd8
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/unix/Makefile.in
@@ -0,0 +1,15 @@
+thisconfigdir=../../..
+myfulldir=ccapi/common/unix
+mydir=ccapi/common/unix
+BUILDTOP=$(REL)..$(S)..$(S)..
+
+STLIBOBJS=
+OBJS=
+SRCS=
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/autolock.hxx b/krb5-1-7/src/ccapi/common/win/OldCC/autolock.hxx
new file mode 100644
index 000000000..bbd773488
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/autolock.hxx
@@ -0,0 +1,53 @@
+/*
+
+   Copyright (C) 1998 Danilo Almeida.  All rights reserved.
+
+   automatic stack-based locking object
+
+   This file is part of FIFS (Framework for Implementing File Systems). 
+
+   This software is distributed with NO WARRANTY OF ANY KIND.  No
+   author or distributor accepts any responsibility for the
+   consequences of using it, or for whether it serves any particular
+   purpose or works at all, unless he or she says so in writing.
+   Refer to the included modified Alladin Free Public License (the
+   "License") for full details.
+
+   Every copy of this software must include a copy of the License, in
+   a plain ASCII text file named COPYING.  The License grants you the
+   right to copy, modify and redistribute this software, but only
+   under certain conditions described in the License.  Among other
+   things, the License requires that the copyright notice and this
+   notice be preserved on all copies.
+
+*/
+
+#ifndef __AUTOLOCK_HXX__
+#define __AUTOLOCK_HXX__
+
+#include <windows.h>
+
+class CcOsLock {
+    CRITICAL_SECTION cs;
+    bool valid;
+public:
+    CcOsLock()      {InitializeCriticalSection(&cs);   valid = true; }
+    ~CcOsLock()     {DeleteCriticalSection(&cs);       valid = false;}
+    void lock()     {if (valid) EnterCriticalSection(&cs);}
+    void unlock()   {if (valid) LeaveCriticalSection(&cs);}
+#if 0
+    bool trylock()  {return valid ? (TryEnterCriticalSection(&cs) ? true : false)
+                                  : false; }
+#endif
+};
+
+class CcAutoLock {
+    CcOsLock& m_lock;
+public:
+    static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); };
+    static void Stop (CcAutoLock*& a) { delete a; a = 0; };
+    CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); }
+    ~CcAutoLock() { m_lock.unlock(); }
+};
+
+#endif /* __AUTOLOCK_HXX */
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.cxx b/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.cxx
new file mode 100644
index 000000000..729104de7
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.cxx
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+    }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+    Init::InitInfo& info
+    );
+
+DWORD
+Init::Info(
+    InitInfo& info
+    )
+{
+    // This funciton will not do automatic initialization.
+    CcAutoLock AL(s_lock);
+    if (!s_init) {
+        memset(&info, 0, sizeof(info));
+        return s_error ? s_error : ERROR_INVALID_HANDLE;
+    } else {
+        info = s_info;
+        return 0;
+    }
+}
+
+DWORD
+Init::Initialize() {
+    CcAutoLock AL(s_lock);
+    cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+    if (s_init) {
+        s_refcount++;
+        return 0;
+        }
+    SecureClient s;
+    DWORD status = 0;
+    OSVERSIONINFO osvi;
+    BOOL isSupportedVersion = FALSE;
+    memset(&s_info, 0, sizeof(s_info));
+    memset(&osvi, 0, sizeof(osvi));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    status = !GetVersionEx(&osvi);       // Returns a boolean.  Invert to 0 is OK.
+
+    if (!status) {
+        switch(osvi.dwPlatformId) {
+        case VER_PLATFORM_WIN32_WINDOWS:
+            s_info.isNT = FALSE;
+            isSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32_NT:
+            s_info.isNT = TRUE;
+            isSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32s:
+        default:
+            s_info.isNT = FALSE;
+            break;
+            }
+    
+        if (!isSupportedVersion) {
+            cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+            status  = 1;
+            }
+        }
+
+    if (!status) {status  = !s_info.isNT;}
+
+    if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+    if (!status) {
+        s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+            GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+        if (!s_info.fRpcBindingSetAuthInfoEx) {
+            cci_debug_printf("  Running on NT but could not find RpcBindinSetAuthInfoEx");
+            status = 1;
+            }
+        }
+    
+    if (!status) {
+        s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+            GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+        if (!s_info.fRpcServerRegisterIfEx) {
+            cci_debug_printf("  Running on NT but could not find RpcServerRegisterIfEx");
+            status = 1;
+            }
+        }
+
+    if (!status) {
+        status = SecureClient::Attach();
+        if (status) {
+            cci_debug_printf("  SecureClient::Attach() failed (%u)", status);
+            }
+        }
+
+    if (status) {
+        memset(&s_info, 0, sizeof(s_info));
+        if (s_hRpcDll) {
+            FreeLibrary(s_hRpcDll);
+            s_hRpcDll = 0;
+        }
+        cci_debug_printf("  Init::Attach() failed (%u)", status);
+    } else {
+        s_refcount++;
+        s_init = true;
+        ShowInfo(s_info);
+    }
+    s_error = status;
+    return status;
+}
+
+DWORD
+Init::Cleanup(
+    )
+{
+    CcAutoLock AL(s_lock);
+    s_refcount--;
+    if (s_refcount) return 0;
+    if (!s_init) return 0;
+    DWORD error = 0;
+    if (s_hRpcDll) {
+        FreeLibrary(s_hRpcDll);
+        s_hRpcDll = 0;
+    }
+    error = SecureClient::Detach();
+    memset(&s_info, 0, sizeof(s_info));
+    s_init = false;
+    s_error = 0;
+    if (error) {
+        cci_debug_printf("  Init::Detach() had an error (%u)", error);
+        }
+    return error;
+}
+
+static
+void
+ShowInfo(
+    Init::InitInfo& info
+    )
+{
+    if (info.isNT) {
+        cci_debug_printf("  Running on Windows NT using secure mode");
+    } else {
+        cci_debug_printf("  Running insecurely on non-NT Windows");
+    }
+    return;
+}
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.def b/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.def
new file mode 100644
index 000000000..57113f094
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/ccutil.def
@@ -0,0 +1,5 @@
+;LIBRARY		COMERR32
+HEAPSIZE	8192
+
+EXPORTS
+    
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.c b/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.c
new file mode 100644
index 000000000..cf881cda1
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.c
@@ -0,0 +1,140 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "cci_debugging.h"
+#include "util.h"
+
+BOOL isNT() {
+    OSVERSIONINFO osvi;
+    DWORD   status              = 0;
+    BOOL    bSupportedVersion   = FALSE;
+    BOOL    bIsNT               = FALSE;
+
+    memset(&osvi, 0, sizeof(osvi));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    status = !GetVersionEx(&osvi);       // Returns a boolean.  Invert to 0 is OK.
+
+    if (!status) {
+        switch(osvi.dwPlatformId) {
+        case VER_PLATFORM_WIN32_WINDOWS:
+            bIsNT = FALSE;
+            bSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32_NT:
+            bIsNT = TRUE;
+            bSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32s:
+        default:
+            bIsNT = FALSE;
+            break;
+            }
+    
+        if (!bSupportedVersion) {
+            cci_debug_printf("%s Running on an unsupported version of Windows", __FUNCTION__);
+            status  = 1;
+            }
+        }
+
+    return (!status && bIsNT && bSupportedVersion);
+    }
+
+char*   allocEventName(char* uuid_string, char* suffix) {
+    LPSTR       event_name      = NULL;
+    cc_int32    err             = ccNoError;
+
+    event_name = malloc(strlen(uuid_string) + strlen(suffix) + 3);
+    if (!event_name) err = cci_check_error(ccErrNoMem);
+
+    if (!err) {
+        strcpy(event_name, uuid_string);
+        strcat(event_name, "_");
+        strcat(event_name, suffix);
+        }
+
+    return event_name;
+    }
+
+HANDLE createThreadEvent(char* uuid, char* suffix) {
+    LPSTR                   event_name  = NULL;
+    HANDLE                  hEvent      = NULL;
+    PSECURITY_ATTRIBUTES    psa         = 0;        // Everything having to do with
+    SECURITY_ATTRIBUTES     sa          = { 0 };    // sa, psa, security is copied
+    DWORD                   status      = 0;        // from the previous implementation.
+
+    psa = isNT() ? &sa : 0;
+
+    if (isNT()) {
+        sa.nLength = sizeof(sa);
+        status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+        cci_check_error(status);
+        }
+
+    if (!status) {
+        event_name = allocEventName(uuid, suffix);
+        if (!event_name) status = cci_check_error(ccErrNoMem);
+        }
+#if 0
+    cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
+#endif    
+    if (!status) {
+        hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
+        if (!hEvent)     status = cci_check_error(GetLastError());
+        }
+
+    if (!status) ResetEvent(hEvent);
+
+    
+    if (event_name) free(event_name);
+    if (isNT())     free(sa.lpSecurityDescriptor);
+
+    return hEvent;
+    }
+
+HANDLE openThreadEvent(char* uuid, char* suffix) {
+    LPSTR   event_name  = NULL;
+    HANDLE  hEvent      = NULL;
+    DWORD   status      = 0;
+
+    event_name = allocEventName(uuid, suffix);
+    if (!event_name) status = cci_check_error(ccErrNoMem);
+#if 0
+    cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
+#endif
+    if (!status) {
+        hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name);
+        if (!hEvent) status = cci_check_error(GetLastError());
+        }
+
+    if (event_name) free(event_name);
+
+    return hEvent;
+    }
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.h b/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.h
new file mode 100644
index 000000000..073412893
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/ccutils.h
@@ -0,0 +1,49 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 __CCUTILS_H__
+#define __CCUTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+#define REPLY_SUFFIX    (char*)"reply"
+#define LISTEN_SUFFIX   (char*)"listen"
+
+BOOL    isNT();
+char*   allocEventName   (char* uuid, char* suffix);
+HANDLE  createThreadEvent(char* uuid, char* suffix);
+HANDLE  openThreadEvent  (char* uuid, char* suffix);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CCUTILS_H__ */
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/init.cxx b/krb5-1-7/src/ccapi/common/win/OldCC/init.cxx
new file mode 100644
index 000000000..feb7ad3ad
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/init.cxx
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+    }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+    Init::InitInfo& info
+    );
+
+DWORD
+Init::Info(
+    InitInfo& info
+    )
+{
+    // This funciton will not do automatic initialization.
+    CcAutoLock AL(s_lock);
+    if (!s_init) {
+        memset(&info, 0, sizeof(info));
+        return s_error ? s_error : ERROR_INVALID_HANDLE;
+    } else {
+        info = s_info;
+        return 0;
+    }
+}
+
+DWORD
+Init::Initialize() {
+    CcAutoLock AL(s_lock);
+//    cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+    if (s_init) {
+        s_refcount++;
+        return 0;
+        }
+    SecureClient s;
+    DWORD status = 0;
+    OSVERSIONINFO osvi;
+    BOOL isSupportedVersion = FALSE;
+    memset(&s_info, 0, sizeof(s_info));
+    memset(&osvi, 0, sizeof(osvi));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    status = !GetVersionEx(&osvi);       // Returns a boolean.  Invert to 0 is OK.
+
+    if (!status) {
+        switch(osvi.dwPlatformId) {
+        case VER_PLATFORM_WIN32_WINDOWS:
+            s_info.isNT = FALSE;
+            isSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32_NT:
+            s_info.isNT = TRUE;
+            isSupportedVersion = TRUE;
+            break;
+        case VER_PLATFORM_WIN32s:
+        default:
+            s_info.isNT = FALSE;
+            break;
+            }
+    
+        if (!isSupportedVersion) {
+            cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+            status  = 1;
+            }
+        }
+
+    if (!status) {status  = !s_info.isNT;}
+
+    if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+    if (!status) {
+        s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+            GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+        if (!s_info.fRpcBindingSetAuthInfoEx) {
+            cci_debug_printf("  Running on NT but could not find RpcBindinSetAuthInfoEx");
+            status = 1;
+            }
+        }
+    
+    if (!status) {
+        s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+            GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+        if (!s_info.fRpcServerRegisterIfEx) {
+            cci_debug_printf("  Running on NT but could not find RpcServerRegisterIfEx");
+            status = 1;
+            }
+        }
+
+    if (!status) {
+        status = SecureClient::Attach();
+        if (status) {
+            cci_debug_printf("  SecureClient::Attach() failed (%u)", status);
+            }
+        }
+
+    if (status) {
+        memset(&s_info, 0, sizeof(s_info));
+        if (s_hRpcDll) {
+            FreeLibrary(s_hRpcDll);
+            s_hRpcDll = 0;
+        }
+        cci_debug_printf("  Init::Attach() failed (%u)", status);
+    } else {
+        s_refcount++;
+        s_init = true;
+        ShowInfo(s_info);
+    }
+    s_error = status;
+    return status;
+}
+
+DWORD
+Init::Cleanup(
+    )
+{
+    CcAutoLock AL(s_lock);
+    s_refcount--;
+    if (s_refcount) return 0;
+    if (!s_init) return 0;
+    DWORD error = 0;
+    if (s_hRpcDll) {
+        FreeLibrary(s_hRpcDll);
+        s_hRpcDll = 0;
+    }
+    error = SecureClient::Detach();
+    memset(&s_info, 0, sizeof(s_info));
+    s_init = false;
+    s_error = 0;
+    if (error) {
+        cci_debug_printf("  Init::Detach() had an error (%u)", error);
+        }
+    return error;
+}
+
+static
+void
+ShowInfo(
+    Init::InitInfo& info
+    )
+{
+    if (info.isNT) {
+        cci_debug_printf("  Running on Windows NT using secure mode");
+    } else {
+        cci_debug_printf("  Running insecurely on non-NT Windows");
+    }
+    return;
+}
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/init.hxx b/krb5-1-7/src/ccapi/common/win/OldCC/init.hxx
new file mode 100644
index 000000000..9bac7f8f9
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/init.hxx
@@ -0,0 +1,102 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#pragma once
+#include "autolock.hxx"
+#include <rpc.h>
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)(
+    IN RPC_BINDING_HANDLE Binding,
+    IN unsigned char __RPC_FAR * ServerPrincName,
+    IN unsigned long AuthnLevel,
+    IN unsigned long AuthnSvc,
+    IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+    IN unsigned long AuthzSvc,
+    IN RPC_SECURITY_QOS *SecurityQos OPTIONAL
+    );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)(
+    IN RPC_BINDING_HANDLE Binding,
+    IN unsigned short __RPC_FAR * ServerPrincName,
+    IN unsigned long AuthnLevel,
+    IN unsigned long AuthnSvc,
+    IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+    IN unsigned long AuthzSvc, OPTIONAL
+    IN RPC_SECURITY_QOS *SecurityQOS
+    );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)(
+    IN RPC_IF_HANDLE IfSpec,
+    IN UUID __RPC_FAR * MgrTypeUuid,
+    IN RPC_MGR_EPV __RPC_FAR * MgrEpv,
+    IN unsigned int Flags,
+    IN unsigned int MaxCalls,
+    IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback
+    );
+
+#ifdef UNICODE
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW"
+#else
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA"
+#endif
+
+#define FN_RpcServerRegisterIfEx   "RpcServerRegisterIfEx"
+
+class Init
+{
+public:
+    struct InitInfo {
+        BOOL isNT;
+        FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx;
+        FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx;
+    };
+
+    static DWORD Initialize();
+    static DWORD Cleanup();
+    static DWORD Info(InitInfo& info);
+
+    static bool Initialized() { return s_init; }
+
+private:
+    static CcOsLock s_lock;
+    static DWORD s_refcount;
+    static DWORD s_error;
+    static bool s_init;
+    static InitInfo s_info;
+    static HINSTANCE s_hRpcDll;
+};
+
+#define INIT_INIT_EX(trap, error) \
+do \
+{ \
+    if (!Init::Initialized()) \
+    { \
+        DWORD rc = Init::Initialize(); \
+        if (rc) return (trap) ? (error) : rc; \
+    } \
+} while(0)
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/name.h b/krb5-1-7/src/ccapi/common/win/OldCC/name.h
new file mode 100644
index 000000000..7b442e09c
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/name.h
@@ -0,0 +1,38 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#pragma once
+
+#ifdef _WIN64
+#define CCAPI_MODULE "krbcc64"
+#else
+#define CCAPI_MODULE "krbcc32"
+#endif
+#define CCAPI_DLL CCAPI_MODULE ".dll"
+#define CCAPI_EXE CCAPI_MODULE "s.exe"
+
+#define CCAPI_DLL   "ccapi.dll"
+#define CCAPI_EXE   "ccapiserver.exe"
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/opts.cxx b/krb5-1-7/src/ccapi/common/win/OldCC/opts.cxx
new file mode 100644
index 000000000..bd5f503ea
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/opts.cxx
@@ -0,0 +1,188 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <opts.hxx>
+
+#if 0
+const struct Opts*
+GetOpts(
+    )
+{
+    bool done = false;
+    struct Opts* o;
+    if (!(o = new Opts))
+        goto cleanup;
+    if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1]))
+        goto cleanup;
+    if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1]))
+        goto cleanup;
+    strcpy(o->pszString, opts.pszString);
+    strcpy(o->pszEndpoint, opts.pszEndpoint);
+    done = true;
+ cleanup:
+    if (!done) {
+        FreeOpts(o);
+        o = 0;
+    }
+    return o;
+}
+
+void
+FreeOpts(
+    struct Opts* o
+    )
+{
+    if (o) {
+        if (o->pszString)
+            delete [] o->pszString;
+        if (o->pszEndpoint)
+            delete [] o->pszEndpoint;
+        delete o;
+    }
+}
+#endif
+
+bool
+ParseOpts::IsValidOpt(
+    char ch
+    )
+{
+    return (m_ValidOpts[ch % 256] != 0);
+}
+
+void
+ParseOpts::PrintOpt(
+    char ch,
+    char* text
+    )
+{
+    if (IsValidOpt(ch))
+        fprintf(stderr, "  -%c %s\n", ch, text);
+}
+
+void
+ParseOpts::UsageOpts(
+    char * program,
+    int code
+    )
+{
+    fprintf(stderr, "Usage: %s [options]\n", program);
+    PrintOpt('k', "stop server");
+#ifdef CCAPI_TEST_OPTIONS
+    PrintOpt('s', "string");
+    PrintOpt('e', "endpoint");
+    PrintOpt('m', "maxcalls");
+    PrintOpt('n', "mincalls");
+    PrintOpt('f', "flag_wait_op");
+    PrintOpt('u', "unprotected");
+    PrintOpt('b', "use security callback");
+#endif
+    PrintOpt('c', "output debug info to console");
+    exit(code);
+}
+
+void
+ParseOpts::SetValidOpts(
+    char* valid_opts
+    )
+{
+    memset(m_ValidOpts, 0, sizeof(m_ValidOpts));
+    char *p = valid_opts;
+    for (p = valid_opts; *p; p++) {
+        m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1;
+    }
+}
+
+void
+ParseOpts::Parse(
+    Opts& opts,
+    int argc,
+    char **argv
+    )
+{
+    int i;
+    for (i = 1; i < argc; i++) {
+        if ((*argv[i] == '-') || (*argv[i] == '/')) {
+            char ch = tolower(*(argv[i]+1));
+            if (!IsValidOpt(ch))
+                UsageOpts(argv[0]);
+            switch (ch) {
+            case 'k':
+                opts.bShutdown = TRUE;
+                break;
+#ifdef CCAPI_TEST_OPTIONS
+            case 's':
+                opts.pszString = argv[++i];
+                break;
+            case 'e':
+                opts.pszEndpoint = argv[++i];
+                break;
+            case 'm':
+                opts.cMaxCalls = (unsigned int) atoi(argv[++i]);
+                break;
+            case 'n':
+                opts.cMinCalls = (unsigned int) atoi(argv[++i]);
+                break;
+            case 'f':
+                opts.fDontWait = (unsigned int) atoi(argv[++i]);
+                break;
+            case 'u':
+                opts.bDontProtect = TRUE;
+                break;
+            case 'b':
+                opts.bSecCallback = TRUE;
+                break;
+#endif
+            case 'c':
+                opts.bConsole = TRUE;
+                break;
+            case 'h':
+            case '?':
+            default:
+                UsageOpts(argv[0]);
+            }
+        }
+        else
+            UsageOpts(argv[0]);
+    }
+
+}
+
+ParseOpts::ParseOpts(char* valid_opts)
+{
+    SetValidOpts(valid_opts);
+}
+
+ParseOpts::ParseOpts()
+{
+}
+
+ParseOpts::~ParseOpts()
+{
+}
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/opts.hxx b/krb5-1-7/src/ccapi/common/win/OldCC/opts.hxx
new file mode 100644
index 000000000..755ce4ae6
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/opts.hxx
@@ -0,0 +1,56 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#pragma once
+
+class ParseOpts
+{
+public:
+    struct Opts {
+        char* pszString;
+        char* pszEndpoint;
+        unsigned int cMinCalls;
+        unsigned int cMaxCalls;
+        unsigned int fDontWait;
+        bool bDontProtect;
+        bool bShutdown;
+        bool bSecCallback;
+        bool bConsole;
+    };
+
+    ParseOpts(char* valid_opts);
+    ParseOpts();
+    ~ParseOpts();
+    void SetValidOpts(char* valid_opts);
+    void Parse(Opts& opts, int argc, char **argv);
+
+private:
+    bool IsValidOpt(char ch);
+    void PrintOpt(char ch, char* text);
+    void UsageOpts(char* program, int code = 0);
+
+    char m_ValidOpts[256];
+};
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/secure.cxx b/krb5-1-7/src/ccapi/common/win/OldCC/secure.cxx
new file mode 100644
index 000000000..99ba08a25
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/secure.cxx
@@ -0,0 +1,161 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+    }
+
+CcOsLock SecureClient::s_lock;
+DWORD SecureClient::s_refcount = 0;
+DWORD SecureClient::s_error = 0;
+HANDLE SecureClient::s_hToken = 0;
+
+#include "util.h"
+
+#define SC "SecureClient::"
+
+DWORD
+SecureClient::Attach(
+    )
+{
+    CcAutoLock AL(s_lock);
+    if (s_hToken) {
+        s_refcount++;
+        return 0;
+    }
+    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, 
+                         &s_hToken)) {
+        s_refcount++;
+        s_error = 0;
+    } else {
+        s_hToken = 0;
+        s_error = GetLastError();
+    }
+    return s_error;
+}
+
+DWORD
+SecureClient::Detach(
+    )
+{
+    CcAutoLock AL(s_lock);
+    s_refcount--;
+    if (s_refcount) return 0;
+    if (!s_hToken) return 0;
+    DWORD error = 0;
+    if (!CloseHandle(s_hToken))
+        error = GetLastError();
+    s_hToken = 0;
+    s_error = 0;
+    return error;
+}
+
+DWORD SecureClient::Token(HANDLE& hToken) {
+    // This function will not do automatic initialization.
+    CcAutoLock AL(s_lock);
+    hToken = 0;
+    if (!s_hToken) {
+        cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error);
+        return s_error ? s_error : ERROR_INVALID_HANDLE;
+        } 
+    else {
+        DWORD status = 0;
+        if (!DuplicateHandle(GetCurrentProcess(), s_hToken, 
+                             GetCurrentProcess(), &hToken, 0, FALSE, 
+                             DUPLICATE_SAME_ACCESS)) {
+            status = GetLastError();
+            cci_debug_printf("  Could not duplicate handle (%u)", status);
+            }
+        return status;
+        }
+    }
+
+void
+SecureClient::Start(SecureClient*& s) {
+    s = new SecureClient;
+}
+
+void
+SecureClient::Stop(SecureClient*& s) {
+    delete s;
+    s = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* This constructor turns off impersonation.
+ * It is OK for OpenThreadToken to return an error -- that just means impersonation
+ * is off.
+ */
+SecureClient::SecureClient():
+    m_Error(0),
+    m_hToken(0),
+    m_NeedRestore(false) {
+
+    HANDLE hThread = GetCurrentThread();
+    HANDLE hThDuplicate;
+    
+    int status  = DuplicateHandle(  GetCurrentProcess(),
+                                    hThread,
+                                    GetCurrentProcess(),
+                                    &hThDuplicate,
+                                    TOKEN_ALL_ACCESS,
+                                    FALSE,
+                                    0);
+    if (!status) return;
+
+    if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) {
+        m_Error = GetLastError();
+        return;
+        }
+    if (SetThreadToken(&hThDuplicate, NULL)) {
+        m_NeedRestore = true;
+    } else {
+        m_Error = GetLastError();
+        }
+    CloseHandle(hThDuplicate);
+    }
+
+SecureClient::~SecureClient() {
+    if (m_NeedRestore) {
+        HANDLE hThread = GetCurrentThread();
+        if (!SetThreadToken(&hThread, m_hToken)) {
+            m_Error = cci_check_error(GetLastError());
+            }
+        }
+    if (m_hToken) {
+        if (!CloseHandle(m_hToken)) {
+            m_Error = cci_check_error(GetLastError());
+            }
+        }
+    }
+
+DWORD SecureClient::Error() {
+    return m_Error;
+    }
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/secure.hxx b/krb5-1-7/src/ccapi/common/win/OldCC/secure.hxx
new file mode 100644
index 000000000..3714c6f84
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/secure.hxx
@@ -0,0 +1,60 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#pragma once
+
+#include <windows.h>
+#include "autolock.hxx"
+
+class SecureClient
+{
+public:
+    static DWORD Attach();
+    static DWORD Detach();
+    static DWORD Token(HANDLE& hToken);
+    static void Start(SecureClient*& s);
+    static void Stop(SecureClient*& s);
+
+#if 0
+    static DWORD CheckImpersonation();
+    static bool IsImp();
+    static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary);
+#endif
+
+    SecureClient();
+    ~SecureClient();
+    DWORD Error();
+
+private:
+    static CcOsLock s_lock;
+    static DWORD s_refcount;
+    static DWORD s_error;
+    static HANDLE s_hToken;
+
+    DWORD m_Error;
+    HANDLE m_hToken;
+    bool m_NeedRestore;
+};
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/util.cxx b/krb5-1-7/src/ccapi/common/win/OldCC/util.cxx
new file mode 100644
index 000000000..dd4a2694a
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/util.cxx
@@ -0,0 +1,520 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <windows.h>
+#include <stdio.h>  // for _snprintf
+#include <malloc.h>
+#include <stdlib.h>
+
+extern "C" {
+#include "cci_debugging.h"
+#include "ccutils.h"
+    }
+
+#include "util.h"
+#include "secure.hxx"
+
+
+void* malloc_alloc_p(size_t size) {
+    return malloc(size);
+    }
+
+void free_alloc_p(void *pptr) {
+    void **real_pptr = (void**)pptr;
+    if (*real_pptr) {
+        free(*real_pptr);
+        *real_pptr = 0;
+        }
+    }
+
+extern "C" DWORD alloc_textual_sid(
+    PSID pSid,          // binary Sid
+    LPSTR *pTextualSid  // buffer for Textual representaion of Sid
+    ) {
+    PSID_IDENTIFIER_AUTHORITY psia;
+    DWORD dwSubAuthorities;
+    DWORD dwSidRev = SID_REVISION;
+    DWORD dwCounter;
+    DWORD dwSidSize;
+
+    *pTextualSid = 0;
+
+    //
+    // test if Sid passed in is valid
+    //
+    if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER;
+
+    // obtain SidIdentifierAuthority
+    psia = GetSidIdentifierAuthority(pSid);
+ 
+    // obtain sidsubauthority count
+    dwSubAuthorities =* GetSidSubAuthorityCount(pSid);
+ 
+    //
+    // compute buffer length
+    // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
+    //
+    dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
+    *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize);
+    if (!*pTextualSid)
+        return GetLastError();
+
+    LPSTR TextualSid = *pTextualSid;
+
+    //
+    // prepare S-SID_REVISION-
+    //
+    wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
+ 
+    //
+    // prepare SidIdentifierAuthority
+    //
+    if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
+    {
+        wsprintf(TextualSid + lstrlen(TextualSid),
+                 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
+                 (USHORT)psia->Value[0],
+                 (USHORT)psia->Value[1],
+                 (USHORT)psia->Value[2],
+                 (USHORT)psia->Value[3],
+                 (USHORT)psia->Value[4],
+                 (USHORT)psia->Value[5]);
+    }
+    else
+    {
+        wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"),
+                 (ULONG)(psia->Value[5]      )   +
+                 (ULONG)(psia->Value[4] <<  8)   +
+                 (ULONG)(psia->Value[3] << 16)   +
+                 (ULONG)(psia->Value[2] << 24)   );
+    }
+ 
+    //
+    // loop through SidSubAuthorities
+    //
+    for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
+    {
+        wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"),
+                 *GetSidSubAuthority(pSid, dwCounter) );
+    }
+    return 0;
+}
+
+DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) {
+    DWORD status = 0;
+    DWORD size = 0;
+    *pptu = 0;
+
+    GetTokenInformation(hToken, TokenUser, *pptu, 0, &size);
+    if (size == 0) status = GetLastError();
+
+    if (!status) {
+        if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size)))
+            status = GetLastError();
+        }
+
+    if (!status) {
+        if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size))
+            status = GetLastError();
+        }
+
+    if (status && *pptu) {
+        free_alloc_p(pptu);
+        }
+    return status;
+    }
+
+DWORD
+alloc_username(
+    PSID Sid,
+    LPSTR* pname,
+    LPSTR* pdomain = 0
+    )
+{
+    DWORD status = 0;
+    DWORD name_len = 0;
+    DWORD domain_len = 0;
+    SID_NAME_USE snu;
+    LPSTR name = 0;
+    LPSTR domain = 0;
+
+    *pname = 0;
+    if (pdomain) *pdomain = 0;
+
+    LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu);
+    if ((name_len == 0) || (domain_len == 0)) status = GetLastError();
+
+    if (!status) {
+        if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError();
+        }
+
+    if (status) {
+        if (name)   free_alloc_p(&name);
+        if (domain) free_alloc_p(&domain);
+        } 
+    else {
+        if (pdomain) {
+            *pname = name;
+            *pdomain = domain;
+            } 
+        else {
+            DWORD size = name_len + domain_len + 1;
+            *pname = (LPSTR)malloc_alloc_p(size);
+            if (!*pname) status = GetLastError();
+            else _snprintf(*pname, size, "%s\\%s", name, domain);
+            }
+        }
+    return status;
+    }
+
+DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) {
+    TOKEN_STATISTICS ts;
+    DWORD len;
+
+    if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len))
+        return GetLastError();
+    *pAuthId = ts.AuthenticationId;
+    return 0;
+    }
+
+DWORD
+alloc_name_9x(
+    LPSTR* pname,
+    LPSTR postfix
+    )
+{
+    char prefix[] = "krbcc";
+    DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1;
+
+    *pname = (LPSTR)malloc_alloc_p(len);
+    if (!*pname) return GetLastError();
+    _snprintf(*pname, len, "%s.%s", prefix, postfix);
+    return 0;
+}
+
+DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) {
+    DWORD status = 0;
+    HANDLE hToken = 0;
+    LUID auth_id;
+#ifdef _DEBUG
+    PTOKEN_USER ptu = 0;
+    LPSTR name = 0;
+    LPSTR domain = 0;
+    LPSTR sid = 0;
+#endif
+    char prefix[] = "krbcc";
+    // Play it safe and say 3 characters are needed per 8 bits (byte).
+    // Note that 20 characters are needed for a 64-bit number in
+    // decimal (plus one for the string termination.
+    // and include room for sessionId.
+    char lid[3*sizeof(LUID)+1+5];
+    DWORD sessionId;
+    DWORD len = 0;
+
+    *pname = 0;
+
+    status = SecureClient::Token(hToken);
+
+    if (!status) {
+        status = get_authentication_id(hToken, &auth_id);
+        }
+
+    if (!status) {
+        if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId))
+	        sessionId = 0;
+        }
+
+#ifdef _DEBUG
+    if (!status) {status = alloc_token_user(hToken, &ptu);}
+    if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);}
+    if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);}
+#endif
+
+    if (!status) {
+        _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId);
+        lid[sizeof(lid)-1] = 0; // be safe
+
+        len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1;
+        *pname = (LPSTR)malloc_alloc_p(len);
+        if (!*pname) status = GetLastError();
+        }
+
+    //
+    // We used to allocate a name of the form:
+    // "prefix.domain.name.sid.lid.postfix" (usually under 80
+    // characters, depending on username).  However, XP thought this
+    // was "invalid" (too long?) for some reason.
+    //
+    // Therefore, we now use "prefix.lid.postfix"
+    // and for Terminal server we use "prefix.lid.sessionId.postfix"
+    //
+
+    if (!status) {
+        _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix);
+        }
+
+#ifdef _DEBUG
+    if (sid)
+        free_alloc_p(&sid);
+    if (name)
+        free_alloc_p(&name);
+    if (domain)
+        free_alloc_p(&domain);
+    if (ptu)
+        free_alloc_p(&ptu);
+#endif
+    if (hToken && hToken != INVALID_HANDLE_VALUE)
+        CloseHandle(hToken);
+    if (status && *pname)
+        free_alloc_p(pname);
+    return status;
+}
+
+extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) {
+    return isNT ? alloc_name_NT(pname, postfix) : 
+        alloc_name_9x(pname, postfix);
+    }
+
+extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) {
+    DWORD status = 0;
+    HANDLE hToken = 0;
+    PTOKEN_USER ptu = 0;
+    PSID pSid = 0;
+    PACL pAcl = 0;
+    DWORD size = 0;
+    SECURITY_DESCRIPTOR sd;
+
+    *ppsd = 0;
+
+    if (!status) {status = SecureClient::Token(hToken);}
+
+    // Get SID:
+    if (!status) {status = alloc_token_user(hToken, &ptu);}
+
+    if (!status) {
+        size = GetLengthSid(ptu->User.Sid);
+        pSid = (PSID) malloc_alloc_p(size);
+        if (!pSid) status = GetLastError();
+        }
+    if (!status) {
+        if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError();
+        }
+
+    if (!status) {
+        // Prepare ACL:
+        size = sizeof(ACL);
+        // Add an ACE:
+        size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
+        pAcl = (PACL) malloc_alloc_p(size);
+        if (!pAcl) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError();
+        }
+
+    if (!status) {
+        // Prepare SD itself:
+        if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER;
+        }
+
+    if (!status) {
+        // We now have a SD.  Let's copy it.
+        {
+            // This should not succeed.  Instead it should give us the size.
+            BOOL ok = MakeSelfRelativeSD(&sd, 0, &size);
+            }
+        if (size == 0) status = GetLastError();
+        }
+
+    if (!status) {
+        *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size);
+        if (!*ppsd) status = GetLastError();
+        }
+
+    if (!status) {
+        if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError();
+        }
+
+    if (ptu)                free_alloc_p(&ptu);
+    if (pSid)               free_alloc_p(&pSid);
+    if (pAcl)               free_alloc_p(&pAcl);
+    if (hToken && hToken != INVALID_HANDLE_VALUE)   CloseHandle(hToken);
+    if (status && *ppsd)    free_alloc_p(ppsd);
+    return status;
+}
+
+DWORD
+alloc_module_file_name(
+    char* module,
+    char** pname
+    )
+{
+    const DWORD max = 8192;
+    DWORD status = 0;
+    DWORD got = 0;
+    DWORD size = 512; // use low number to test...
+    HMODULE h = 0;
+    BOOL ok = FALSE;
+    char* name = 0;
+
+    if (!pname)
+        return ERROR_INVALID_PARAMETER;
+    *pname = 0;
+
+    h = GetModuleHandle(module);
+
+    if (!h) return GetLastError();
+
+    // We assume size < max and size > 0
+    while (!status && !ok) {
+        if (size > max) {
+            // XXX - Assert?
+            status = ERROR_INVALID_DATA;
+            continue;
+        }
+        if (name) free_alloc_p(&name);
+        name = (char*)malloc_alloc_p(size + 1);
+        if (!name) {
+            status = ERROR_NOT_ENOUGH_MEMORY;
+            continue;
+        }
+        name[size] = 0;
+        got = GetModuleFileName(h, name, size);
+        if (!got) {
+            status = GetLastError();
+            // sanity check:
+            if (!status) {
+                // XXX - print nasty message...assert?
+                status = ERROR_INVALID_DATA;
+            }
+            continue;
+        }
+        // To know we're ok, we need to verify that what we got
+        // was bigger than GetModuleSize thought it got.
+        ok = got && (got < size) && !name[got];
+        size *= 2;
+    }
+    if (status && name)
+        free_alloc_p(&name);
+    else
+        *pname = name;
+    return status;
+}
+
+DWORD
+alloc_module_dir_name(
+    char* module,
+    char** pname
+    )
+{
+    DWORD status = alloc_module_file_name(module, pname);
+    if (!status) {
+        char* name = *pname;
+        char* p = name + strlen(name);
+        while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
+        if (p < name) {
+            free_alloc_p(pname);
+            status = ERROR_INVALID_DATA;
+        } else {
+            *p = 0;
+        }
+    }
+    return status;
+}
+
+DWORD
+alloc_module_dir_name_with_file(
+    char* module,
+    char* file,
+    char** pname
+    )
+{
+    DWORD status = alloc_module_dir_name(module, pname);
+    if (!status) {
+        char* name = *pname;
+        size_t name_size = strlen(name);
+        size_t size = name_size + 1 + strlen(file) + 1;
+        char* result = (char*)malloc_alloc_p(size);
+        if (!result) {
+            status = ERROR_NOT_ENOUGH_MEMORY;
+            free_alloc_p(pname);
+        } else {
+            strcpy(result, name);
+            result[name_size] = '\\';
+            strcpy(result + name_size + 1, file);
+            free_alloc_p(pname);
+            *pname = result;
+        }
+    }
+    return status;
+}
+
+DWORD alloc_cmdline_2_args(char* prog,
+                           char* arg1,
+                           char* arg2,
+                           char** pname) {
+    DWORD   status  = 0;
+    size_t  size    = strlen(prog) + strlen(arg1) + strlen(arg2) + 4;
+    char*   result  = (char*)malloc_alloc_p(size);
+    if (!result) {
+        status = ERROR_NOT_ENOUGH_MEMORY;
+        } 
+    else {
+        strcpy(result, prog);
+        strcat(result, " ");
+        strcat(result, arg1);
+        strcat(result, " ");
+        strcat(result, arg2);
+        *pname = result;
+        }
+    cci_debug_printf("%s made <%s>", __FUNCTION__, result);
+    return status;
+    }
diff --git a/krb5-1-7/src/ccapi/common/win/OldCC/util.h b/krb5-1-7/src/ccapi/common/win/OldCC/util.h
new file mode 100644
index 000000000..4a83c644a
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/OldCC/util.h
@@ -0,0 +1,89 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 __UTIL_H__
+#define __UTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+BOOL isNT();
+
+void*
+user_allocate(
+    size_t size
+    );
+
+void
+user_free(
+    void* ptr
+    );
+
+void
+free_alloc_p(
+    void* pptr
+    );
+
+DWORD
+alloc_name(
+    LPSTR* pname,
+    LPSTR postfix,
+    BOOL isNT
+    );
+
+DWORD
+alloc_own_security_descriptor_NT(
+    PSECURITY_DESCRIPTOR* ppsd
+    );
+
+DWORD
+alloc_module_dir_name(
+    char* module,
+    char** pname
+    );
+
+DWORD
+alloc_module_dir_name_with_file(
+    char* module,
+    char* file,
+    char** pname
+    );
+
+DWORD alloc_cmdline_2_args(
+    char* prog,
+    char* arg1,
+    char* arg2,
+    char** pname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UTIL_H__ */
diff --git a/krb5-1-7/src/ccapi/common/win/cci_os_debugging.c b/krb5-1-7/src/ccapi/common/win/cci_os_debugging.c
new file mode 100644
index 000000000..6e6a7158d
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/cci_os_debugging.c
@@ -0,0 +1,39 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <stdarg.h>
+
+#include "cci_os_debugging.h"
+#include "win-utils.h"
+
+/* ------------------------------------------------------------------------ */
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args) {
+    printf  ( "%s %ld ", timestamp(), GetCurrentThreadId() );
+    vprintf ( in_format, in_args );
+    printf  ( "\n" );
+    }
diff --git a/krb5-1-7/src/ccapi/common/win/cci_os_identifier.c b/krb5-1-7/src/ccapi/common/win/cci_os_identifier.c
new file mode 100644
index 000000000..34659e097
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/cci_os_identifier.c
@@ -0,0 +1,58 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 "cci_common.h"
+#include "cci_os_identifier.h"
+
+#include <rpc.h>
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string) {
+    cc_int32        err = ccNoError;
+    UUID            uuid;
+    char*           uuidStringTemp;
+
+    err = UuidCreate(&uuid);
+
+    if (!err) {
+        err = UuidToString(&uuid, &uuidStringTemp);
+        }
+
+    if (!err) {
+        *out_uuid_string = malloc(1+strlen(uuidStringTemp));
+
+        if (*out_uuid_string) {
+            strcpy(*out_uuid_string, uuidStringTemp);
+            }
+
+        RpcStringFree(&uuidStringTemp);
+        }
+
+    cci_debug_printf("cci_os_identifier_new_uuid returning %s", *out_uuid_string);
+
+    return cci_check_error (err);
+    }
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/ccs_reply.Acf b/krb5-1-7/src/ccapi/common/win/ccs_reply.Acf
new file mode 100644
index 000000000..aea44d74c
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/ccs_reply.Acf
@@ -0,0 +1,31 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+[implicit_handle(handle_t ccs_reply_IfHandle)]
+
+interface ccs_reply {
+    [async] ccapi_listen();
+    }
diff --git a/krb5-1-7/src/ccapi/common/win/ccs_reply.Idl b/krb5-1-7/src/ccapi/common/win/ccs_reply.Idl
new file mode 100644
index 000000000..9035a4d00
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/ccs_reply.Idl
@@ -0,0 +1,60 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA),
+  version(1.0),
+  pointer_default(unique)
+]
+
+/* This interface sends a cci_stream via rpc.
+ */
+
+interface ccs_reply {
+    const long HSIZE = sizeof(void*);
+
+/* The reply from the server to a request from the client: */
+void ccs_rpc_request_reply(
+    [in]                    const long              rpcmsg,         /* Message type */
+    [in, size_is(HSIZE)]    const char              tsphandle[],
+    [in, string]            const char*             uuid,
+    [in]                    const long              srvStartTime,   /* Server Start Time */
+    [in]                    const long              cbIn,           /* Length of buffer */
+    [in,  size_is(cbIn)]    const unsigned char     chIn[],         /* Data buffer */
+    [out]                   long*                   status );       /* Return code */
+
+void ccs_rpc_connect_reply(
+    [in]                    const long      rpcmsg,         /* Message type */
+    [in, size_is(HSIZE)]    const char      tsphandle[],
+    [in, string]            const char*     uuid,
+    [in]                    const long      srvStartTime,   /* Server Start Time */
+    [out]                   long*           status );       /* Return code */
+
+void ccapi_listen(
+    handle_t                hBinding,   
+    [in]                    const long rpcmsg,              /* Message type */
+    [out]                   long* status );                 /* Return code */
+
+    }
diff --git a/krb5-1-7/src/ccapi/common/win/ccs_request.Acf b/krb5-1-7/src/ccapi/common/win/ccs_request.Acf
new file mode 100644
index 000000000..625bcce65
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/ccs_request.Acf
@@ -0,0 +1,31 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+[implicit_handle(handle_t ccs_request_IfHandle)]
+interface ccs_request
+{
+
+}
diff --git a/krb5-1-7/src/ccapi/common/win/ccs_request.idl b/krb5-1-7/src/ccapi/common/win/ccs_request.idl
new file mode 100644
index 000000000..8c68fd8f3
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/ccs_request.idl
@@ -0,0 +1,58 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA),
+  version(1.0),
+  pointer_default(unique)
+]
+
+interface ccs_request {
+
+typedef char CC_CHAR;
+typedef unsigned char CC_UCHAR;
+typedef int CC_INT32;
+typedef unsigned int CC_UINT32;
+
+const long HSIZE = sizeof(void*);
+
+void ccs_rpc_request(
+    [in]                        const long  rpcmsg,         /* Message type */
+    [in, size_is(HSIZE)]        const char  tsphandle[],
+    [in,  string]               const char* pszUUID,        /* Requestor's UUID */
+    [in]                        const long  lenRequest,     /* Length of buffer */
+    [in,  size_is(lenRequest)]  const char* pszRequest,     /* Data buffer */
+    [in]                        const long  serverStartTime,/* Which server session we're talking to */
+    [out]                       long*       status );       /* Return code */
+
+void ccs_rpc_connect(
+    [in]                        const long  rpcmsg,         /* Message type */
+    [in, size_is(HSIZE)]        const char  tsphandle[],
+    [in,  string]               const char* pszUUID,        /* Requestor's UUID */
+    [out]                       long*       status );       /* Return code */
+
+CC_UINT32 ccs_authenticate(
+    [in, string]                const CC_CHAR* name );
+}
diff --git a/krb5-1-7/src/ccapi/common/win/tls.c b/krb5-1-7/src/ccapi/common/win/tls.c
new file mode 100644
index 000000000..5e0e11d7a
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/tls.c
@@ -0,0 +1,106 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <malloc.h>
+
+#include "tls.h"
+
+struct tspdata* new_tspdata(char* uuid, time_t sst) {
+    struct tspdata* p   = (struct tspdata*)malloc(sizeof(struct tspdata));
+    if (p) {
+        memset(p, 0, sizeof(struct tspdata));
+        p->_sst = sst;
+        if (uuid) {strncpy(p->_uuid, uuid, UUID_SIZE-1);}
+        }
+    return p;
+    }
+
+void delete_tspdata(struct tspdata* p) {
+    if (p)          free(p);
+    }
+
+void tspdata_setUUID(struct tspdata* p, unsigned char __RPC_FAR* uuidString) {
+    strncpy(p->_uuid, uuidString, UUID_SIZE-1);
+    };
+
+void         tspdata_setConnected (struct tspdata* p, BOOL b)           {p->_CCAPI_Connected = b;}
+
+void         tspdata_setReplyEvent(struct tspdata* p, HANDLE h)         {p->_replyEvent = h;}
+
+void         tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState) {
+    p->_rpcState = rpcState;}
+
+void         tspdata_setSST       (struct tspdata* p, time_t t)         {p->_sst = t;}
+
+void         tspdata_setStream    (struct tspdata* p, k5_ipc_stream s)   {p->_stream = s;}
+
+
+BOOL         tspdata_getConnected (const struct tspdata* p)         {return p->_CCAPI_Connected;}
+
+HANDLE       tspdata_getReplyEvent(const struct tspdata* p)         {return p->_replyEvent;}
+
+time_t       tspdata_getSST       (const struct tspdata* p)         {return p->_sst;}
+
+k5_ipc_stream tspdata_getStream    (const struct tspdata* p)         {return p->_stream;}
+
+char*        tspdata_getUUID      (const struct tspdata* p)         {return p->_uuid;}
+
+RPC_ASYNC_STATE* tspdata_getRpcAState (const struct tspdata* p)     {return p->_rpcState;}
+
+BOOL WINAPI PutTspData(DWORD dwTlsIndex, struct tspdata* dw) {
+    LPVOID              lpvData; 
+    struct tspdata**    pData;  // The stored memory pointer 
+
+    // Retrieve a data pointer for the current thread:
+    lpvData = TlsGetValue(dwTlsIndex); 
+
+    // If NULL, allocate memory for the TLS slot for this thread:
+    if (lpvData == NULL) {
+        lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata)); 
+        if (lpvData == NULL)                      return FALSE;
+        if (!TlsSetValue(dwTlsIndex, lpvData))    return FALSE;
+        }
+
+    pData = (struct tspdata**) lpvData; // Cast to my data type.
+    // In this example, it is only a pointer to a DWORD
+    // but it can be a structure pointer to contain more complicated data.
+
+    (*pData) = dw;
+    return TRUE;
+    }
+
+BOOL WINAPI GetTspData(DWORD dwTlsIndex, struct tspdata**  pdw) {
+    struct tspdata*  pData;      // The stored memory pointer 
+
+    pData = (struct tspdata*)TlsGetValue(dwTlsIndex); 
+    if (pData == NULL) return FALSE;
+    (*pdw) = pData;
+    return TRUE;
+    }
+
+
diff --git a/krb5-1-7/src/ccapi/common/win/tls.h b/krb5-1-7/src/ccapi/common/win/tls.h
new file mode 100644
index 000000000..b6761c8bb
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/tls.h
@@ -0,0 +1,73 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* Thread local storage for client threads. */
+
+#ifndef _tls_h
+#define _tls_h
+
+#include "windows.h"
+#include "time.h"
+#include "rpc.h"
+
+#include "cci_stream.h"
+
+#define UUID_SIZE   128
+
+/* The client code can be run in any client thread.  
+   The thread-specific data is defined here.
+ */
+
+struct tspdata {
+    BOOL                _CCAPI_Connected;
+    RPC_ASYNC_STATE*    _rpcState;
+    HANDLE              _replyEvent;
+    time_t              _sst;
+    k5_ipc_stream        _stream;
+    char                _uuid[UUID_SIZE];
+    };
+
+struct tspdata* new_tspdata          (char* uuid, time_t sst);
+void            delete_tspdata       (struct tspdata* p);
+
+void            tspdata_setConnected (struct tspdata* p, BOOL b);
+void            tspdata_setReplyEvent(struct tspdata* p, HANDLE h);
+void            tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState);
+void            tspdata_setSST       (struct tspdata* p, time_t t);
+void            tspdata_setStream    (struct tspdata* p, k5_ipc_stream s);
+void            tspdata_setUUID      (struct tspdata* p, unsigned char __RPC_FAR* uuidString);
+HANDLE          tspdata_getReplyEvent(const struct tspdata* p);
+
+BOOL             tspdata_getConnected(const struct tspdata* p);
+RPC_ASYNC_STATE* tspdata_getRpcAState(const struct tspdata* p);
+time_t           tspdata_getSST      (const struct tspdata* p);
+k5_ipc_stream     tspdata_getStream   (const struct tspdata* p);
+char*            tspdata_getUUID     (const struct tspdata* p);
+
+BOOL WINAPI PutTspData(DWORD tlsIndex, struct tspdata*  dw);
+BOOL WINAPI GetTspData(DWORD tlsIndex, struct tspdata** pdw);
+
+#endif _tls_h
diff --git a/krb5-1-7/src/ccapi/common/win/win-utils.c b/krb5-1-7/src/ccapi/common/win/win-utils.c
new file mode 100644
index 000000000..f60ee3b8f
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/win-utils.c
@@ -0,0 +1,69 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 <time.h>
+#include "windows.h"
+#include <stdlib.h>
+#include <malloc.h>
+
+
+#include "win-utils.h"
+#include "cci_debugging.h"
+
+#pragma warning (disable : 4996)
+
+#define UUID_SIZE   128
+
+char*           clientPrefix        = "CCAPI_CLIENT_";
+char*           serverPrefix        = "CCS_LISTEN_";
+unsigned char*  pszProtocolSequence = "ncalrpc";
+
+#define         MAX_TIMESTAMP   40
+char            _ts[MAX_TIMESTAMP];
+
+char* clientEndpoint(const char* UUID) {
+    char* _clientEndpoint   = (char*)malloc(strlen(UUID) + strlen(clientPrefix) + 2);
+    strcpy(_clientEndpoint, clientPrefix);
+    strncat(_clientEndpoint, UUID, UUID_SIZE);
+//    cci_debug_printf("%s returning %s", __FUNCTION__, _clientEndpoint);
+    return _clientEndpoint;
+    }       
+
+char* serverEndpoint(const char* user) {
+    char* _serverEndpoint   = (char*)malloc(strlen(user) + strlen(serverPrefix) + 2);
+    strcpy(_serverEndpoint, serverPrefix);
+    strncat(_serverEndpoint, user, UUID_SIZE);
+    return _serverEndpoint;
+    }       
+
+char* timestamp() {
+    SYSTEMTIME  _stime;
+    GetSystemTime(&_stime);
+    GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &_stime, "HH:mm:ss", _ts, sizeof(_ts)-1);
+    return _ts;
+    }
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/common/win/win-utils.h b/krb5-1-7/src/ccapi/common/win/win-utils.h
new file mode 100644
index 000000000..5dbb192fa
--- /dev/null
+++ b/krb5-1-7/src/ccapi/common/win/win-utils.h
@@ -0,0 +1,55 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.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 _win_utils_h
+#define _win_utils_h
+
+#ifndef TRUE
+#define TRUE    (1==1)
+#endif
+
+#ifndef FALSE
+#define FALSE   (1==0)
+#endif
+
+static enum ccapiMsgType {
+    CCMSG_INVALID   = 0,
+    CCMSG_CONNECT,
+    CCMSG_REQUEST,
+    CCMSG_CONNECT_REPLY,
+    CCMSG_REQUEST_REPLY,
+    CCMSG_DISCONNECT,
+    CCMSG_LISTEN,
+    CCMSG_PING
+    };
+
+char*                   clientEndpoint(const char* UUID);
+char*                   serverEndpoint(const char* UUID);
+extern unsigned char*   pszProtocolSequence;
+
+char* timestamp();
+
+#endif // _win_utils_h
\ No newline at end of file
diff --git a/krb5-1-7/src/ccapi/doc/CCAPI-Windows-Design.html b/krb5-1-7/src/ccapi/doc/CCAPI-Windows-Design.html
new file mode 100644
index 000000000..72af7e92a
--- /dev/null
+++ b/krb5-1-7/src/ccapi/doc/CCAPI-Windows-Design.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Windows CCAPI RPC design
+
+
+
+
+

Proposed RPC design for Windows CCAPI clients and server

+

The proposal is for a single user; the solution is replicated for each user logged onto the PC.

+

Conventions & clarifications

+

"Client" and "server" refer to the CCAPI client and server.

+

The CCAPI client acts as both an RPC client and RPC server and the CCAPI server acts as both an RPC client and RPC server.

+
    +
  • The RPC call from the CCAPI client to the CCAPI server is called the "request." In this mode, the CCAPI client is the RPC client and the CCAPI server is the RPC server.
  • +
  • The RPC call from the CCAPI server to the CCAPI client is called the "reply." In this mode, the CCAPI client is the RPC server and the CCAPI server is the RPC client.
  • +
+

The Windows username is referred to below as "<USER>."

+

The Windows Logon Security Identifier is referred to as "<LSID>."

+

<UUID> means a thread-specific UUID.

+

<SST> means server start time, a time_t.

+

A description of client and server authentication has not been added yet.

+

Design Requirements

+
    +
  • The server's OS-independent code is single threaded, because it must operate on platforms that do not allow multiple threads.
  • +
  • The client and server must be able to maintain connections, where state is maintained between individual messages.
  • +
  • Individual messages must be handled in a single threaded server.
  • +
  • The server must be able to detect when a client dies, so that any connection state can be cleaned up.
  • +
+

Design

+

The server and each client create an RPC endpoint. The server's endpoint is CCS_<LSID> and the client's endpoint is CCAPI_<UUID>, where each client geta a UUID.

+

On Windows, the server's ccs_pipe_t type is a char* and is set to the client UUID.

+

How is the request handled in the server and the reply sent to the client?

+

One straightforward way is for the reply to be the returned data in the request RPC call (an [out] parameter). That is, data passed from the RPC server to the RPC client. The request handler calls ccs_server_handle_request. Eventually, the server code calls ccs_os_server_send_reply, which saves the reply somewhere. When the server eventually returns to the request handler, the handler returns the saved reply to the client.

+

But this doesn't work. If two clients A and B ask for the same lock, A will acquire the lock and B will have to wait. But if the single threaded server waits for B's lock, it will never handle A's unlock message. Therefore the server must return to B's request handler and not send a reply to B. So this method will not work.

+

Instead, there are listener and worker threads in Windows-specific code.

+

The client's cci_os_ipc function waits for ccs_reply. The client sends the request, including it's UUID, from which the server can construct the endpoint on which to call ccs_reply.

+

The server's listener thread listens for RPC requests. The request handler puts each request/reply endpoint in a queue and returns to the client.

+

The server's worker thread removes items from the queue, calls ccs_server_handle_request. ccs_server_handle_request takes both the request data and the client UUID . Eventually ccs_os_server_send_reply is called, with the reply data and client UUID in the reply_pipe. ccs_os_server_send_reply calls ccs_reply on the client's endpoint, which sends the reply to the client.

+

Is there any security issue with the client listening for RPC calls from the server?

+

Connections

+

If the client wants state to be maintained on the server, the client creates a connection. When the connection is closed, the server cleans up any state associated with the connection.

+

Any given thread in an application process could want to create a connection. When cci_ipc_thread_init is called, the connection thread-local variables are initialized. New connections are created when cci_os_ipc() (via _cci_ipc_send) is called and no connection was previously established. Basically we lazily establish connections so the client doesn't talk to the server until it has to.

+

Detecting client exit

+

The server must be able to detect when clients disappear, so the server can free any resources that had been held for the client.

+

The Windows RPC API does not appear to provide a notification for an endpoint disappearing. It does provide a way to ask if an endpoint is listening. This is useful for polling, but we want a better performing solution than that.

+

The client has an isAlive function on its endpoint.

+

To detect the client disappearing without using polling, the server makes an asynchronous call to the isAlive function on the client's endpoint. The isAlive function never returns. When the client exits for any reason, it's endpoint will be closed and the server's function call will return an error. The asynchronous call on the server means no additional threads are used.

+

Windows provides a number of notification methods to signal I/O completion. Among them are I/O completion ports and callback functions. I chose callback functions because they appear to consume fewer resources.

+

RPC Endpoint / Function summary

+
    +
  • The server creates one CCS_<LSID> endpoint to listen for connection requests and client requests. + It has the functions +
      +
    • ccs_rpc_connect(msgtype, UUIDlen, <UUID>, status)
    • +
    • ccs_rpc_request(msgtype, UUIDlen, <UUID>, msglen, msg, SST, status) called by client. NB: The windows server sets the in_client_pipe to the in_reply_pipe.
      +
    • +
    +
  • +
  • Each client thread creates a CCAPI_<UUID> endpoint. It has the functions +
      +
    • isAlive [function never returns.]
    • +
    • ccs_rpc_request_reply(msgtype, SST, replylen, reply, status)
    • +
    • ccs_rpc_connect_reply(msgtype, SST, status
    • +
    +
  • +
+

Windows-specific implementation details

+

Client CCAPI library initialization:

+

This code runs when the CCAPI DLL is loaded.

+
    +
  • ?
  • +
+

Client initialization:

+

This code runs when cci_os_ipc_thread_init is called:

+
    +
  • Generate <UUID> and save in thread-specific storage. This serves as the client ID / ccs_pipe_t.
  • +
  • Create client endpoint.
  • +
  • Listen on client endpoint.
  • +
  • Create canonical server connection endpoint from the <LSID>, which the client and server should have in common.
  • +
  • Test if server is listening to the CCS_<LSID> endpoint. +
      +
    • If not, quit. (! Start it?)
    • +
    +
  • +
  • Call ccs_connect(<UUID>) on the CCS_<LSID> endpoint.
  • +
  • Save SST in thread-specific storage.
  • +
+

Server initialization:

+

[old]

+
    +
  • Server is initialized by client starting a new process. There should be only one server process per Windows username.
  • +
+

[new]

+
    +
  • Server is started by kfwlogon (as is done currently).
  • +
  • Capture server start time (SST).
  • +
  • Start listener thread, create listener endpoint, listen on CCS_<LSID> endpoint.
  • +
+

Establishing a connection:

+
    +
  • Client calls ccs_connect(<UUID>) on server's CCS_<LSID> endpoint.
  • +
  • Client gets back and stores SST in thread-specific storage.
  • +
  • If new connection, server ... +
      +
    • adds connection to connection table
    • +
    • calls isAlive on CCAPI_<UUID>. +
        +
      • NB: isAlive never returns.
      • +
      +
    • +
    +
  • +
+

Client request:

+

The server's reply to the client's request is not synchronous.

+
    +
  • Client calls ccs_rpc_request(msglen, msg, msgtype, UUIDlen, <UUID>, SST, status) on server's endpoint.
  • +
  • Server listen thread receives message, queues request.
  • +
  • Server worker thread dequeues request, processes, calls ccs_rpc_reply(replylen, reply, msgtype, status) on CCAPI_<UUID>.
  • +
  • Server checks SST. If server's SST is different, it means server has restarted since client created connection.
  • +
  • Client receives reply.
  • +
+

Detecting client exit

+
    +
  • When connection created, client created an endpoint.
  • +
  • Server calls isAlive on client's endpoint.
  • +
  • When isAlive returns, the server's notification callback will be called. Call back routine queues a DISCONNECT pseudo-message. When the server's worker thread handles the DISCONNECT, it will release connection resources.
  • +
+

Detecting server exit

+
    +
  • Client's call to ccs_rpc_request will return an error if the server has gone away.
  • +
+

 

+

------
+ Stop:
+Start:

+ + diff --git a/krb5-1-7/src/ccapi/lib/Makefile.in b/krb5-1-7/src/ccapi/lib/Makefile.in new file mode 100644 index 000000000..76df8126f --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/Makefile.in @@ -0,0 +1,65 @@ +thisconfigdir=../.. +myfulldir=ccapi/lib +mydir=ccapi/lib +BUILDTOP=$(REL)..$(S).. +SUBDIRS=unix +LOCALINCLUDES=-I$(srcdir)/../common + +SHLIB_EXPDEPS= $(COM_ERR_DEPLIB) +SHLIB_EXPLIBS=-lcom_err + +LIBBASE=krb5-ccapi +LIBMAJOR=1 +LIBMINOR=0 + +STOBJLISTS= \ + OBJS.ST \ + unix/OBJS.ST \ + ../common/OBJS.ST \ + ../common/unix/OBJS.ST + +STLIBOBJS= \ + ccapi_ccache.o \ + ccapi_ccache_iterator.o \ + ccapi_context.o \ + ccapi_context_change_time.o \ + ccapi_credentials.o \ + ccapi_credentials_iterator.o \ + ccapi_err.o \ + ccapi_ipc.o \ + ccapi_string.o \ + ccapi_v2.o + +OBJS= \ + $(OUTPRE)ccapi_ccache.$(OUTPRE) \ + $(OUTPRE)ccapi_ccache_iterator.$(OUTPRE) \ + $(OUTPRE)ccapi_context.$(OUTPRE) \ + $(OUTPRE)ccapi_context_change_time.$(OUTPRE) \ + $(OUTPRE)ccapi_credentials.$(OUTPRE) \ + $(OUTPRE)ccapi_credentials_iterator.$(OUTPRE) \ + $(OUTPRE)ccapi_err.$(OUTPRE) \ + $(OUTPRE)ccapi_ipc.$(OUTPRE) \ + $(OUTPRE)ccapi_string.$(OUTPRE) \ + $(OUTPRE)ccapi_v2.$(OUTPRE) + +SRCS= \ + ccapi_ccache.c \ + ccapi_ccache_iterator.c \ + ccapi_context.c \ + ccapi_context_change_time.c \ + ccapi_credentials.c \ + ccapi_credentials_iterator.c \ + ccapi_err.c \ + ccapi_ipc.c \ + ccapi_string.c \ + ccapi_v2.c + +ccapi_err.c ccapi_err.h : ccapi_err.et + +all-unix:: all-libobjs all-liblinks +clean-unix:: clean-libobjs clean-liblinks clean-libs + +@lib_frag@ +@libobj_frag@ + +# +++ Dependency line eater +++ diff --git a/krb5-1-7/src/ccapi/lib/ccapi.exports b/krb5-1-7/src/ccapi/lib/ccapi.exports new file mode 100644 index 000000000..92c859bd7 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi.exports @@ -0,0 +1 @@ +cc_initialize diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ccache.c b/krb5-1-7/src/ccapi/lib/ccapi_ccache.c new file mode 100644 index 000000000..57c6f83aa --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ccache.c @@ -0,0 +1,794 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccapi_ccache.h" + +#include "ccapi_string.h" +#include "ccapi_credentials.h" +#include "ccapi_credentials_iterator.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_ccache_d { + cc_ccache_f *functions; +#if TARGET_OS_MAC + cc_ccache_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_time_t last_wait_for_change_time; + cc_uint32 compat_version; +} *cci_ccache_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_ccache_d cci_ccache_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0 +}; + +cc_ccache_f cci_ccache_f_initializer = { + ccapi_ccache_release, + ccapi_ccache_destroy, + ccapi_ccache_set_default, + ccapi_ccache_get_credentials_version, + ccapi_ccache_get_name, + ccapi_ccache_get_principal, + ccapi_ccache_set_principal, + ccapi_ccache_store_credentials, + ccapi_ccache_remove_credentials, + ccapi_ccache_new_credentials_iterator, + ccapi_ccache_move, + ccapi_ccache_lock, + ccapi_ccache_unlock, + ccapi_ccache_get_last_default_time, + ccapi_ccache_get_change_time, + ccapi_ccache_compare, + ccapi_ccache_get_kdc_time_offset, + ccapi_ccache_set_kdc_time_offset, + ccapi_ccache_clear_kdc_time_offset, + ccapi_ccache_wait_for_change +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_new (cc_ccache_t *out_ccache, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = NULL; + + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache = malloc (sizeof (*ccache)); + if (ccache) { + *ccache = cci_ccache_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + ccache->functions = malloc (sizeof (*ccache->functions)); + if (ccache->functions) { + *ccache->functions = cci_ccache_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&ccache->identifier, in_identifier); + } + + if (!err) { + *out_ccache = (cc_ccache_t) ccache; + ccache = NULL; /* take ownership */ + } + + ccapi_ccache_release ((cc_ccache_t) ccache); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_write (cc_ccache_t in_ccache, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!in_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (ccache->identifier, in_stream); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = ccErrBadParam; } + + if (!err) { + cci_identifier_release (ccache->identifier); + + free ((char *) ccache->functions); + free (ccache); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_destroy_msg_id, + ccache->identifier, + NULL, + NULL); + } + + if (!err) { + err = ccapi_ccache_release (io_ccache); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_default_msg_id, + ccache->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_credentials_version_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (reply, out_credentials_version); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + char *name = NULL; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_name_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &name); + } + + if (!err) { + err = cci_string_new (out_name, name); + } + + k5_ipc_stream_release (reply); + k5_ipc_stream_free_string (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *principal = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_principal_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &principal); + } + + if (!err) { + err = cci_string_new (out_principal, principal); + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + k5_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_principal_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = cci_credentials_union_write (in_credentials_union, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_store_credentials_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache, + cc_credentials_t in_credentials) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = cci_credentials_write (in_credentials, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_remove_credentials_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_new_credentials_iterator_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_credentials_iterator_new (out_credentials_iterator, identifier); + } + + k5_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ +/* Note: message is sent as the destination to avoid extra work on the */ +/* server when deleting it the source ccache. */ + +cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t source_ccache = (cci_ccache_t) io_source_ccache; + cci_ccache_t destination_ccache = (cci_ccache_t) io_destination_ccache; + k5_ipc_stream request = NULL; + + if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = cci_identifier_write (source_ccache->identifier, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_move_msg_id, + destination_ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_lock_type); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_block); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_lock_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_unlock_msg_id, + ccache->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_last_default_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_last_default_time_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_time (reply, out_last_default_time); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_change_time_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_time (reply, out_change_time); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_time (request, ccache->last_wait_for_change_time); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_wait_for_change_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_time (reply, &ccache->last_wait_for_change_time); + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + cci_ccache_t compare_to_ccache = (cci_ccache_t) in_compare_to_ccache; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_ccache) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (ccache->identifier, + compare_to_ccache->identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_time_offset) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_kdc_time_offset_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_time (reply, out_time_offset); + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = k5_ipc_stream_write_time (request, in_time_offset); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_kdc_time_offset_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_clear_kdc_time_offset_msg_id, + ccache->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache, + cc_uint32 *out_compat_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_compat_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_compat_version = ccache->compat_version; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache, + cc_uint32 in_compat_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache->compat_version = in_compat_version; + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ccache.h b/krb5-1-7/src/ccapi/lib/ccapi_ccache.h new file mode 100644 index 000000000..1a449c2fb --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ccache.h @@ -0,0 +1,106 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CCACHE_H +#define CCAPI_CCACHE_H + +#include "cci_common.h" + +cc_int32 cci_ccache_new (cc_ccache_t *out_ccache, + cci_identifier_t in_identifier); + +cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache); + +cc_int32 cci_ccache_write (cc_ccache_t in_ccache, + k5_ipc_stream in_stream); + +cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version); + +cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache, + cc_string_t *out_name); + +cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal); + +cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal); + +cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union); + +cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache, + cc_credentials_t in_credentials); + +cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache); + +cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time); + +cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache, + cc_time_t *out_change_time); + +cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache); + +cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal); + +cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset); + +cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset); + +cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version); + +cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache, + cc_uint32 *out_compat_version); + +cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache, + cc_uint32 in_compat_version); + + +#endif /* CCAPI_CCACHE_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.c b/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.c new file mode 100644 index 000000000..0f5d241f9 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.c @@ -0,0 +1,292 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_ccache_iterator.h" +#include "ccapi_ccache.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_ccache_iterator_d { + cc_ccache_iterator_f *functions; +#if TARGET_OS_MAC + cc_ccache_iterator_f *vector_functions; +#endif + cci_identifier_t identifier; + char *saved_ccache_name; +} *cci_ccache_iterator_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_ccache_iterator_d cci_ccache_iterator_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + NULL +}; + +cc_ccache_iterator_f cci_ccache_iterator_f_initializer = { + ccapi_ccache_iterator_release, + ccapi_ccache_iterator_next, + ccapi_ccache_iterator_clone +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = NULL; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache_iterator = malloc (sizeof (*ccache_iterator)); + if (ccache_iterator) { + *ccache_iterator = cci_ccache_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + ccache_iterator->functions = malloc (sizeof (*ccache_iterator->functions)); + if (ccache_iterator->functions) { + *ccache_iterator->functions = cci_ccache_iterator_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&ccache_iterator->identifier, in_identifier); + } + + if (!err) { + *out_ccache_iterator = (cc_ccache_iterator_t) ccache_iterator; + ccache_iterator = NULL; /* take ownership */ + } + + ccapi_ccache_iterator_release ((cc_ccache_iterator_t) ccache_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + + if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (ccache_iterator->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator; + + if (!io_ccache_iterator) { err = ccErrBadParam; } + + if (!err) { + cc_uint32 initialized = 0; + + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + + if (!err && initialized) { + err = cci_ipc_send (cci_ccache_iterator_release_msg_id, + ccache_iterator->identifier, + NULL, + NULL); + if (err) { + cci_debug_printf ("%s: cci_ipc_send failed with error %d", + __FUNCTION__, err); + err = ccNoError; + } + } + } + + if (!err) { + free ((char *) ccache_iterator->functions); + cci_identifier_release (ccache_iterator->identifier); + free (ccache_iterator->saved_ccache_name); + free (ccache_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint32 initialized = 0; + + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + + if (!err && !initialized) { + /* server doesn't actually exist. Pretend we're empty. */ + err = cci_check_error (ccIteratorEnd); + } + } + + if (!err) { + err = cci_ipc_send (cci_ccache_iterator_next_msg_id, + ccache_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + k5_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + k5_ipc_stream reply = NULL; + cc_uint32 initialized = 0; + cci_identifier_t identifier = NULL; + + if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + } + + if (!err) { + if (initialized) { + err = cci_ipc_send (cci_ccache_iterator_next_msg_id, + ccache_iterator->identifier, + NULL, + &reply); + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + } else { + /* server doesn't actually exist. Make another dummy one. */ + identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + err = cci_ccache_iterator_new (out_ccache_iterator, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator, + const char **out_saved_ccache_name) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + + if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_saved_ccache_name) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_saved_ccache_name = ccache_iterator->saved_ccache_name; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator, + const char *in_saved_ccache_name) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator; + char *new_saved_ccache_name = NULL; + + if (!io_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_saved_ccache_name) { + new_saved_ccache_name = strdup (in_saved_ccache_name); + if (!new_saved_ccache_name) { err = ccErrNoMem; } + } + + if (!err) { + free (ccache_iterator->saved_ccache_name); + + ccache_iterator->saved_ccache_name = new_saved_ccache_name; + new_saved_ccache_name = NULL; /* take ownership */ + } + + free (new_saved_ccache_name); + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.h b/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.h new file mode 100644 index 000000000..9556aa0eb --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ccache_iterator.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CCACHE_ITERATOR_H +#define CCAPI_CCACHE_ITERATOR_H + +#include "cci_common.h" + +cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator, + cci_identifier_t in_identifier); + +cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator); + +cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator); + +cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator, + const char **out_saved_ccache_name); + +cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator, + const char *in_saved_ccache_name); + +#endif /* CCAPI_CCACHE_ITERATOR_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_context.c b/krb5-1-7/src/ccapi/lib/ccapi_context.c new file mode 100644 index 000000000..7ba3db4d2 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_context.c @@ -0,0 +1,834 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccapi_context.h" + +#include "k5-platform.h" + +#include "ccapi_ccache.h" +#include "ccapi_ccache_iterator.h" +#include "ccapi_string.h" +#include "ccapi_ipc.h" +#include "ccapi_context_change_time.h" +#include "ccapi_err.h" + +#include + +typedef struct cci_context_d { + cc_context_f *functions; +#if TARGET_OS_MAC + cc_context_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_uint32 synchronized; + cc_time_t last_wait_for_change_time; +} *cci_context_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_context_d cci_context_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0, + 0 +}; + +cc_context_f cci_context_f_initializer = { + ccapi_context_release, + ccapi_context_get_change_time, + ccapi_context_get_default_ccache_name, + ccapi_context_open_ccache, + ccapi_context_open_default_ccache, + ccapi_context_create_ccache, + ccapi_context_create_default_ccache, + ccapi_context_create_new_ccache, + ccapi_context_new_ccache_iterator, + ccapi_context_lock, + ccapi_context_unlock, + ccapi_context_compare, + ccapi_context_wait_for_change +}; + +static cc_int32 cci_context_sync (cci_context_t in_context, + cc_uint32 in_launch); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +MAKE_INIT_FUNCTION(cci_thread_init); +MAKE_FINI_FUNCTION(cci_thread_fini); + +/* ------------------------------------------------------------------------ */ + +static int cci_thread_init (void) +{ + cc_int32 err = ccNoError; + + if (!err) { + err = cci_context_change_time_thread_init (); + } + + if (!err) { + err = cci_ipc_thread_init (); + } + + if (!err) { + add_error_table (&et_CAPI_error_table); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_thread_fini (void) +{ + if (!INITIALIZER_RAN (cci_thread_init) || PROGRAM_EXITING ()) { + return; + } + + remove_error_table(&et_CAPI_error_table); + cci_context_change_time_thread_fini (); + cci_ipc_thread_fini (); +} + + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cc_initialize (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor) +{ + cc_int32 err = ccNoError; + cci_context_t context = NULL; + static char *vendor_string = "MIT Kerberos CCAPI"; + + if (!out_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = CALL_INIT_FUNCTION (cci_thread_init); + } + + if (!err) { + switch (in_version) { + case ccapi_version_2: + case ccapi_version_3: + case ccapi_version_4: + case ccapi_version_5: + case ccapi_version_6: + case ccapi_version_7: + break; + + default: + err = ccErrBadAPIVersion; + break; + } + } + + if (!err) { + context = malloc (sizeof (*context)); + if (context) { + *context = cci_context_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + context->functions = malloc (sizeof (*context->functions)); + if (context->functions) { + *context->functions = cci_context_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + context->identifier = cci_identifier_uninitialized; + + *out_context = (cc_context_t) context; + context = NULL; /* take ownership */ + + if (out_supported_version) { + *out_supported_version = ccapi_version_max; + } + + if (out_vendor) { + *out_vendor = vendor_string; + } + } + + ccapi_context_release ((cc_context_t) context); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ +/* + * Currently does not need to talk to the server since the server must + * handle cleaning up resources from crashed clients anyway. + * + * NOTE: if server communication is ever added here, make sure that + * krb5_stdcc_shutdown calls an internal function which does not talk to the + * server. krb5_stdcc_shutdown is called from thread fini functions and may + * crash talking to the server depending on what order the OS calls the fini + * functions (ie: if the ipc layer fini function is called first). + */ + +cc_int32 ccapi_context_release (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + + if (!in_context) { err = ccErrBadParam; } + + if (!err) { + cci_identifier_release (context->identifier); + free (context->functions); + free (context); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_get_change_time (cc_context_t in_context, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_get_change_time_msg_id, + context->identifier, + NULL, &reply); + } + + if (!err && k5_ipc_stream_size (reply) > 0) { + cc_time_t change_time = 0; + + /* got a response from the server */ + err = k5_ipc_stream_read_time (reply, &change_time); + + if (!err) { + err = cci_context_change_time_update (context->identifier, + change_time); + } + } + + if (!err) { + err = cci_context_change_time_get (out_change_time); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_wait_for_change (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_time (request, context->last_wait_for_change_time); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_wait_for_change_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = k5_ipc_stream_read_time (reply, &context->last_wait_for_change_time); + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + char *reply_name = NULL; + char *name = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_get_default_ccache_name_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err) { + if (k5_ipc_stream_size (reply) > 0) { + /* got a response from the server */ + err = k5_ipc_stream_read_string (reply, &reply_name); + + if (!err) { + name = reply_name; + } + } else { + name = k_cci_context_initial_ccache_name; + } + } + + if (!err) { + err = cci_string_new (out_name, name); + } + + k5_ipc_stream_release (reply); + k5_ipc_stream_free_string (reply_name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_open_ccache (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_name); + } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_open_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err && !(k5_ipc_stream_size (reply) > 0)) { + err = ccErrCCacheNotFound; + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_open_default_ccache_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err && !(k5_ipc_stream_size (reply) > 0)) { + err = ccErrCCacheNotFound; + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_ccache (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_name); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_default_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_new_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + k5_ipc_stream_release (reply); + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_new_ccache_iterator_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err) { + if (k5_ipc_stream_size (reply) > 0) { + err = cci_identifier_read (&identifier, reply); + } else { + identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + err = cci_ccache_iterator_new (out_iterator, identifier); + } + + k5_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_lock (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_lock_type); + } + + if (!err) { + err = k5_ipc_stream_write_uint32 (request, in_block); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_lock_msg_id, + context->identifier, + request, + NULL); + } + + k5_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_unlock (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_unlock_msg_id, + context->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_compare (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + cci_context_t compare_to_context = (cci_context_t) in_compare_to_context; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_context) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_context_sync (compare_to_context, 0); + } + + if (!err) { + /* If both contexts can't talk to the server, then + * we assume they are equivalent */ + err = cci_identifier_compare (context->identifier, + compare_to_context->identifier, + out_equal); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_context_sync (cci_context_t in_context, + cc_uint32 in_launch) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t new_identifier = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Use the uninitialized identifier because we may be talking */ + /* to a different server which would reject our identifier and */ + /* the point of this message is to sync with the server's id */ + if (in_launch) { + err = cci_ipc_send (cci_context_sync_msg_id, + cci_identifier_uninitialized, + NULL, + &reply); + } else { + err = cci_ipc_send_no_launch (cci_context_sync_msg_id, + cci_identifier_uninitialized, + NULL, + &reply); + } + } + + if (!err) { + if (k5_ipc_stream_size (reply) > 0) { + err = cci_identifier_read (&new_identifier, reply); + } else { + new_identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + cc_uint32 equal = 0; + + err = cci_identifier_compare (context->identifier, new_identifier, &equal); + + if (!err && !equal) { + if (context->identifier) { + cci_identifier_release (context->identifier); + } + context->identifier = new_identifier; + new_identifier = NULL; /* take ownership */ + } + } + + if (!err && context->synchronized) { + err = cci_context_change_time_sync (context->identifier); + } + + if (!err && !context->synchronized) { + /* Keep state about whether this is the first call to avoid always */ + /* modifying the global change time on the context's first ipc call. */ + context->synchronized = 1; + } + + cci_identifier_release (new_identifier); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/lib/ccapi_context.h b/krb5-1-7/src/ccapi/lib/ccapi_context.h new file mode 100644 index 000000000..564f49db9 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_context.h @@ -0,0 +1,87 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CONTEXT_H +#define CCAPI_CONTEXT_H + +#include "cci_common.h" + +/* Used for freeing ccapi context in thread fini calls + * Does not tell the server you are exiting. */ +cc_int32 cci_context_destroy (cc_context_t in_context); + +cc_int32 ccapi_context_release (cc_context_t in_context); + +cc_int32 ccapi_context_get_change_time (cc_context_t in_context, + cc_time_t *out_time); + +cc_int32 ccapi_context_wait_for_change (cc_context_t in_context); + +cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context, + cc_string_t *out_name); + +cc_int32 ccapi_context_open_ccache (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_ccache (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator); + +cc_int32 ccapi_context_lock (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 ccapi_context_unlock (cc_context_t in_context); + +cc_int32 ccapi_context_compare (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal); + +#ifdef WIN32 +void cci_thread_init__auxinit(); +#endif + + +#endif /* CCAPI_CONTEXT_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.c b/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.c new file mode 100644 index 000000000..4efc7db60 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.c @@ -0,0 +1,209 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccapi_context_change_time.h" +#include "cci_common.h" + +#include "k5-thread.h" + +static cci_identifier_t g_change_time_identifer = NULL; +static cc_time_t g_change_time = 0; +static cc_time_t g_change_time_offset = 0; +static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_thread_init (void) +{ + return k5_mutex_finish_init(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ + +void cci_context_change_time_thread_fini (void) +{ + k5_mutex_destroy(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ +/* WARNING! Mutex must be locked when calling this! */ + +static cc_int32 cci_context_change_time_update_identifier (cci_identifier_t in_new_identifier, + cc_uint32 *out_server_ids_match, + cc_uint32 *out_old_server_running, + cc_uint32 *out_new_server_running) +{ + cc_int32 err = ccNoError; + cc_uint32 server_ids_match = 0; + cc_uint32 old_server_running = 0; + cc_uint32 new_server_running = 0; + + if (!in_new_identifier) { err = cci_check_error (err); } + + if (!err && !g_change_time_identifer) { + g_change_time_identifer = cci_identifier_uninitialized; + } + + if (!err) { + err = cci_identifier_compare_server_id (g_change_time_identifer, + in_new_identifier, + &server_ids_match); + } + + if (!err && out_old_server_running) { + err = cci_identifier_is_initialized (g_change_time_identifer, &old_server_running); + } + + if (!err && out_new_server_running) { + err = cci_identifier_is_initialized (in_new_identifier, &new_server_running); + } + + if (!err && !server_ids_match) { + cci_identifier_t new_change_time_identifer = NULL; + + err = cci_identifier_copy (&new_change_time_identifer, in_new_identifier); + + if (!err) { + /* Save the new identifier */ + if (g_change_time_identifer) { + cci_identifier_release (g_change_time_identifer); + } + g_change_time_identifer = new_change_time_identifer; + } + } + + if (!err) { + if (out_server_ids_match ) { *out_server_ids_match = server_ids_match; } + if (out_old_server_running) { *out_old_server_running = old_server_running; } + if (out_new_server_running) { *out_new_server_running = new_server_running; } + } + + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_get (cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + + err = k5_mutex_lock (&g_change_time_mutex); + + if (!err) { + *out_change_time = g_change_time + g_change_time_offset; + k5_mutex_unlock (&g_change_time_mutex); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier, + cc_time_t in_new_change_time) +{ + cc_int32 err = ccNoError; + cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex); + + if (!err) { + if (!in_identifier) { err = cci_check_error (err); } + } + + if (!err) { + if (g_change_time < in_new_change_time) { + /* Only update if it increases the time. May be a different server. */ + g_change_time = in_new_change_time; + cci_debug_printf ("%s: setting change time to %d", + __FUNCTION__, in_new_change_time); + } + } + + if (!err) { + err = cci_context_change_time_update_identifier (in_identifier, + NULL, NULL, NULL); + } + + if (!lock_err) { + k5_mutex_unlock (&g_change_time_mutex); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier) +{ + cc_int32 err = ccNoError; + cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex); + cc_uint32 server_ids_match = 0; + cc_uint32 server_was_running = 0; + cc_uint32 server_is_running = 0; + + if (!err) { + if (!in_new_identifier) { err = cci_check_error (err); } + } + + if (!err) { + err = cci_context_change_time_update_identifier (in_new_identifier, + &server_ids_match, + &server_was_running, + &server_is_running); + } + + if (!err && !server_ids_match) { + /* Increment the change time so callers re-read */ + g_change_time_offset++; + + /* If the server died, absorb the offset */ + if (server_was_running && !server_is_running) { + cc_time_t now = time (NULL); + + g_change_time += g_change_time_offset; + g_change_time_offset = 0; + + /* Make sure the change time increases, ideally with the current time */ + g_change_time = (g_change_time < now) ? now : g_change_time; + } + + cci_debug_printf ("%s noticed server changed (" + "server_was_running = %d; server_is_running = %d; " + "g_change_time = %d; g_change_time_offset = %d", + __FUNCTION__, server_was_running, server_is_running, + g_change_time, g_change_time_offset); + } + + if (!lock_err) { + k5_mutex_unlock (&g_change_time_mutex); + } + + return err; +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.h b/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.h new file mode 100644 index 000000000..ecf3583a9 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_context_change_time.h @@ -0,0 +1,42 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CONTEXT_CHANGE_TIME_H +#define CCAPI_CONTEXT_CHANGE_TIME_H + +#include "cci_common.h" + +cc_int32 cci_context_change_time_thread_init (void); +void cci_context_change_time_thread_fini (void); + +cc_int32 cci_context_change_time_get (cc_time_t *out_change_time); + +cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier, + cc_time_t in_new_change_time); + +cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier); + +#endif /* CCAPI_CONTEXT_CHANGE_TIME_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_credentials.c b/krb5-1-7/src/ccapi/lib/ccapi_credentials.c new file mode 100644 index 000000000..6a3b4cb91 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_credentials.c @@ -0,0 +1,166 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_credentials.h" + +#include "ccapi_string.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_credentials_d { + cc_credentials_union *data; + cc_credentials_f *functions; +#if TARGET_OS_MAC + cc_credentials_f *vector_functions; +#endif + cci_identifier_t identifier; +} *cci_credentials_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_credentials_d cci_credentials_initializer = { + NULL, + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL +}; + +cc_credentials_f cci_credentials_f_initializer = { + ccapi_credentials_release, + ccapi_credentials_compare +}; + +cc_credentials_union cci_credentials_union_initializer = { + 0, + { NULL } +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_read (cc_credentials_t *out_credentials, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = NULL; + + if (!out_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials = malloc (sizeof (*credentials)); + if (credentials) { + *credentials = cci_credentials_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + credentials->functions = malloc (sizeof (*credentials->functions)); + if (credentials->functions) { + *credentials->functions = cci_credentials_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_read (&credentials->identifier, in_stream); + } + + if (!err) { + err = cci_credentials_union_read (&credentials->data, in_stream); + } + + if (!err) { + *out_credentials = (cc_credentials_t) credentials; + credentials = NULL; /* take ownership */ + } + + if (credentials) { ccapi_credentials_release ((cc_credentials_t) credentials); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_write (cc_credentials_t in_credentials, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) in_credentials; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (credentials->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) in_credentials; + cci_credentials_t compare_to_credentials = (cci_credentials_t) in_compare_to_credentials; + + if (!in_credentials ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_credentials) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (credentials->identifier, + compare_to_credentials->identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) io_credentials; + + if (!io_credentials) { err = ccErrBadParam; } + + if (!err) { + cci_credentials_union_release (credentials->data); + free ((char *) credentials->functions); + cci_identifier_release (credentials->identifier); + free (credentials); + } + + return err; +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_credentials.h b/krb5-1-7/src/ccapi/lib/ccapi_credentials.h new file mode 100644 index 000000000..9307e684b --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_credentials.h @@ -0,0 +1,44 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CREDENTIALS_H +#define CCAPI_CREDENTIALS_H + +#include "cci_common.h" + +cc_int32 cci_credentials_read (cc_credentials_t *out_credentials, + k5_ipc_stream in_stream); + +cc_int32 cci_credentials_write (cc_credentials_t in_credentials, + k5_ipc_stream in_stream); + +cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal); + +cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials); + +#endif /* CCAPI_CREDENTIALS_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.c b/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.c new file mode 100644 index 000000000..4571b64f8 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.c @@ -0,0 +1,247 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_credentials_iterator.h" +#include "ccapi_credentials.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_credentials_iterator_d { + cc_credentials_iterator_f *functions; +#if TARGET_OS_MAC + cc_credentials_iterator_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_uint32 compat_version; +} *cci_credentials_iterator_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_credentials_iterator_d cci_credentials_iterator_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0 +}; + +cc_credentials_iterator_f cci_credentials_iterator_f_initializer = { + ccapi_credentials_iterator_release, + ccapi_credentials_iterator_next, + ccapi_credentials_iterator_clone +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = NULL; + + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials_iterator = malloc (sizeof (*credentials_iterator)); + if (credentials_iterator) { + *credentials_iterator = cci_credentials_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + credentials_iterator->functions = malloc (sizeof (*credentials_iterator->functions)); + if (credentials_iterator->functions) { + *credentials_iterator->functions = cci_credentials_iterator_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&credentials_iterator->identifier, in_identifier); + } + + if (!err) { + *out_credentials_iterator = (cc_credentials_iterator_t) credentials_iterator; + credentials_iterator = NULL; /* take ownership */ + } + + if (credentials_iterator) { ccapi_credentials_iterator_release ((cc_credentials_iterator_t) credentials_iterator); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (credentials_iterator->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator; + + if (!io_credentials_iterator) { err = ccErrBadParam; } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_release_msg_id, + credentials_iterator->identifier, + NULL, + NULL); + if (err) { + cci_debug_printf ("%s: cci_ipc_send failed with error %d", + __FUNCTION__, err); + err = ccNoError; + } + } + + if (!err) { + free ((char *) credentials_iterator->functions); + cci_identifier_release (credentials_iterator->identifier); + free (credentials_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + k5_ipc_stream reply = NULL; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_next_msg_id, + credentials_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_credentials_read (out_credentials, reply); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_credentials_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_next_msg_id, + credentials_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_credentials_iterator_new (out_credentials_iterator, identifier); + } + + k5_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator, + cc_uint32 *out_compat_version) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_compat_version ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_compat_version = credentials_iterator->compat_version; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator, + cc_uint32 in_compat_version) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials_iterator->compat_version = in_compat_version; + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.h b/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.h new file mode 100644 index 000000000..84c3d2e22 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_credentials_iterator.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_CREDENTIALS_ITERATOR_H +#define CCAPI_CREDENTIALS_ITERATOR_H + +#include "cci_common.h" + +cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator, + cci_identifier_t in_identifier); + +cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator); + +cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials); + +cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator); + +cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator, + cc_uint32 *out_compat_version); + +cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator, + cc_uint32 in_compat_version); + +#endif /* CCAPI_CREDENTIALS_ITERATOR_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_err.et b/krb5-1-7/src/ccapi/lib/ccapi_err.et new file mode 100644 index 000000000..44cd2d0b5 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_err.et @@ -0,0 +1,74 @@ +# +# $Header$ +# +# Copyright 1998-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_table_base 201 +error_table_manager "Credentials Cache" +error_table CAPI + +# 201 +error_code ccIteratorEnd, "Reached end of iterator" +error_code ccErrBadParam, "Invalid argument" +error_code ccErrNoMem, "Out of memory" +error_code ccErrInvalidContext, "Invalid credentials cache context" +error_code ccErrInvalidCCache, "Invalid credentials cache" + +# 206 +index 5 +error_code ccErrInvalidString, "Invalid credentials cache string" +error_code ccErrInvalidCredentials, "Invalid credentials" +error_code ccErrInvalidCCacheIterator, "Invalid credentials cache iterator" +error_code ccErrInvalidCredentialsIterator, "Invalid credentials iterator" +error_code ccErrInvalidLock, "Invalid iterator" + +# 211 +index 10 +error_code ccErrBadName, "Invalid credentials cache name" +error_code ccErrBadCredentialsVersion, "Invalid credentials cache version (not 4 or 5)" +error_code ccErrBadAPIVersion, "Invalid CCAPI version" +error_code ccErrContextLocked, "Credentials cache context is already locked" +error_code ccErrContextUnlocked, "Credentials cache context is already unlocked" + +# 216 +index 15 +error_code ccErrCCacheLocked, "Credentials cache is already locked" +error_code ccErrCCacheUnlocked, "Credentials cache is already unlocked" +error_code ccErrBadLockType, "Invalid credentials cache lock type" +error_code ccErrNeverDefault, "Credentials cache has never been the default cache" +error_code ccErrCredentialsNotFound, "Credentials not found" + +# 221 +index 20 +error_code ccErrCCacheNotFound, "Credentials cache not found" +error_code ccErrContextNotFound, "Credentials cache context not found" +error_code ccErrServerUnavailable, "Credentials cache server unavailable" +error_code ccErrServerInsecure, "Credentials cache server in this bootstrap is owned by another user" +error_code ccErrServerCantBecomeUID, "Credentials cache server failed to change effective uids" + +# 226 +index 25 +error_code ccErrTimeOffsetNotSet, "Credentials cache time offset not set" + +end diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ipc.c b/krb5-1-7/src/ccapi/lib/ccapi_ipc.c new file mode 100644 index 000000000..43993dc76 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ipc.c @@ -0,0 +1,120 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_ipc.h" +#include "ccapi_os_ipc.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_thread_init (void) +{ + return cci_os_ipc_thread_init (); +} + +/* ------------------------------------------------------------------------ */ + +void cci_ipc_thread_fini (void) +{ + cci_os_ipc_thread_fini (); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 _cci_ipc_send (enum cci_msg_id_t in_request_name, + cc_int32 in_launch_server, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cc_int32 reply_error = 0; + + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + /* in_request_data may be NULL */ + /* out_reply_data may be NULL */ + + if (!err) { + err = cci_message_new_request_header (&request, + in_request_name, + in_identifier); + } + + if (!err && in_request_data) { + err = k5_ipc_stream_write (request, + k5_ipc_stream_data (in_request_data), + k5_ipc_stream_size (in_request_data)); + } + + if (!err) { + err = cci_os_ipc (in_launch_server, request, &reply); + + if (!err && k5_ipc_stream_size (reply) > 0) { + err = cci_message_read_reply_header (reply, &reply_error); + } + } + + if (!err && reply_error) { + err = reply_error; + } + + if (!err && out_reply_data) { + *out_reply_data = reply; + reply = NULL; /* take ownership */ + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + return cci_check_error (_cci_ipc_send (in_request_name, 1, + in_identifier, + in_request_data, + out_reply_data)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + return cci_check_error (_cci_ipc_send (in_request_name, 0, + in_identifier, + in_request_data, + out_reply_data)); +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_ipc.h b/krb5-1-7/src/ccapi/lib/ccapi_ipc.h new file mode 100644 index 000000000..5b7d5d374 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_ipc.h @@ -0,0 +1,45 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_IPC_H +#define CCAPI_IPC_H + +#include "cci_common.h" + +cc_int32 cci_ipc_thread_init (void); +void cci_ipc_thread_fini (void); + +cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCAPI_IPC_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_os_ipc.h b/krb5-1-7/src/ccapi/lib/ccapi_os_ipc.h new file mode 100644 index 000000000..b5e040599 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_os_ipc.h @@ -0,0 +1,39 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_OS_IPC_H +#define CCAPI_OS_IPC_H + +#include "cci_common.h" + +cc_int32 cci_os_ipc_thread_init (void); +void cci_os_ipc_thread_fini (void); + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream); + +#endif /* CCAPI_OS_IPC_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_string.c b/krb5-1-7/src/ccapi/lib/ccapi_string.c new file mode 100644 index 000000000..4f4db6f43 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_string.c @@ -0,0 +1,102 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_string.h" + +/* ------------------------------------------------------------------------ */ + +cc_string_d cci_string_d_initializer = { + NULL, + NULL + VECTOR_FUNCTIONS_INITIALIZER }; + +cc_string_f cci_string_f_initializer = { + ccapi_string_release +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_string_new (cc_string_t *out_string, + char *in_cstring) +{ + cc_int32 err = ccNoError; + cc_string_t string = NULL; + + if (!out_string) { err = cci_check_error (ccErrBadParam); } + if (!in_cstring) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + string = malloc (sizeof (*string)); + if (string) { + *string = cci_string_d_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + string->functions = malloc (sizeof (*string->functions)); + if (string->functions) { + *((cc_string_f *) string->functions) = cci_string_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + string->data = strdup (in_cstring); + if (!string->data) { + err = cci_check_error (ccErrNoMem); + } + + } + + if (!err) { + *out_string = string; + string = NULL; /* take ownership */ + } + + if (string) { ccapi_string_release (string); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_string_release (cc_string_t in_string) +{ + cc_int32 err = ccNoError; + + if (!in_string) { err = ccErrBadParam; } + + if (!err) { + free ((char *) in_string->data); + free ((char *) in_string->functions); + free (in_string); + } + + return err; +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_string.h b/krb5-1-7/src/ccapi/lib/ccapi_string.h new file mode 100644 index 000000000..dec7a7cc7 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_string.h @@ -0,0 +1,37 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCAPI_STRING_H +#define CCAPI_STRING_H + +#include "cci_common.h" + +cc_int32 cci_string_new (cc_string_t *out_string, + char *in_cstring); + +cc_int32 ccapi_string_release (cc_string_t in_string); + +#endif /* CCAPI_STRING_H */ diff --git a/krb5-1-7/src/ccapi/lib/ccapi_v2.c b/krb5-1-7/src/ccapi/lib/ccapi_v2.c new file mode 100644 index 000000000..08100481b --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_v2.c @@ -0,0 +1,918 @@ +/* + * $Header$ + * + * 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. + */ + +#include "cci_common.h" +#include "ccapi_string.h" +#include "ccapi_context.h" +#include "ccapi_ccache.h" +#include "ccapi_ccache_iterator.h" +#include "ccapi_credentials.h" +#include "ccapi_credentials_iterator.h" +#include + +infoNC infoNC_initializer = { NULL, NULL, CC_CRED_UNKNOWN }; + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_remap_version (cc_int32 in_v2_version, + cc_uint32 *out_v3_version) +{ + cc_result err = ccNoError; + + if (!out_v3_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (in_v2_version == CC_CRED_V4) { + *out_v3_version = cc_credentials_v4; + + } else if (in_v2_version == CC_CRED_V5) { + *out_v3_version = cc_credentials_v5; + + } else { + err = ccErrBadCredentialsVersion; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_result _cci_remap_error (cc_result in_error, + const char *in_function, + const char *in_file, + int in_line) +{ + _cci_check_error (in_error, in_function, in_file, in_line); + + if (in_error >= CC_NOERROR && in_error <= CC_ERR_CRED_VERSION) { + return in_error; + } + + switch (in_error) { + case ccNoError: + return CC_NOERROR; + + case ccIteratorEnd: + return CC_END; + + case ccErrBadParam: + case ccErrContextNotFound: + case ccErrInvalidContext: + case ccErrInvalidCredentials: + case ccErrInvalidCCacheIterator: + case ccErrInvalidCredentialsIterator: + case ccErrInvalidLock: + case ccErrBadLockType: + return CC_BAD_PARM; + + case ccErrNoMem: + return CC_NOMEM; + + case ccErrInvalidCCache: + case ccErrCCacheNotFound: + return CC_NO_EXIST; + + case ccErrCredentialsNotFound: + return CC_NOTFOUND; + + case ccErrBadName: + return CC_BADNAME; + + case ccErrBadCredentialsVersion: + return CC_ERR_CRED_VERSION; + + case ccErrBadAPIVersion: + return CC_BAD_API_VERSION; + + case ccErrContextLocked: + case ccErrContextUnlocked: + case ccErrCCacheLocked: + case ccErrCCacheUnlocked: + return CC_LOCKED; + + case ccErrServerUnavailable: + case ccErrServerInsecure: + case ccErrServerCantBecomeUID: + case ccErrBadInternalMessage: + case ccErrClientNotFound: + return CC_IO; + + case ccErrNotImplemented: + return CC_NOT_SUPP; + + default: + cci_debug_printf ("%s(): Unhandled error", __FUNCTION__); + return CC_BAD_PARM; + } +} +#define cci_remap_error(err) _cci_remap_error(err, __FUNCTION__, __FILE__, __LINE__) + + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_shutdown (apiCB **io_context) +{ + cc_result err = ccNoError; + + if (!io_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_release (*io_context); + } + + if (!err) { + *io_context = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_change_time (apiCB *in_context, + cc_time_t *out_change_time) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_get_change_time (in_context, out_change_time); + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_NC_info (apiCB *in_context, + infoNC ***out_info) +{ + cc_result err = CC_NOERROR; + infoNC **info = NULL; + cc_uint64 count = 0; /* Preflight the size */ + cc_uint64 i; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_info ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache_cit *iterator = NULL; + + err = cc_seq_fetch_NCs_begin (in_context, &iterator); + + while (!err) { + ccache_p *ccache = NULL; + + err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator); + + if (!err) { count++; } + + if (ccache) { cc_close (in_context, &ccache); } + } + if (err == CC_END) { err = CC_NOERROR; } + + if (!err) { + err = cc_seq_fetch_NCs_end (in_context, &iterator); + } + } + + if (!err) { + info = malloc (sizeof (*info) * (count + 1)); + if (info) { + for (i = 0; i < count + 1; i++) { info[i] = NULL; } + } else { + err = cci_check_error (CC_NOMEM); + } + } + + if (!err) { + ccache_cit *iterator = NULL; + + err = cc_seq_fetch_NCs_begin (in_context, &iterator); + + for (i = 0; !err && i < count; i++) { + ccache_p *ccache = NULL; + + err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator); + + if (!err) { + info[i] = malloc (sizeof (*info[i])); + if (info[i]) { + *info[i] = infoNC_initializer; + } else { + err = cci_check_error (CC_NOMEM); + } + } + + if (!err) { + err = cc_get_name (in_context, ccache, &info[i]->name); + } + + if (!err) { + err = cc_get_principal (in_context, ccache, &info[i]->principal); + } + + if (!err) { + err = cc_get_cred_version (in_context, ccache, &info[i]->vers); + } + + if (ccache) { cc_close (in_context, &ccache); } + } + + if (!err) { + err = cc_seq_fetch_NCs_end (in_context, &iterator); + } + } + + if (!err) { + *out_info = info; + info = NULL; + } + + if (info) { cc_free_NC_info (in_context, &info); } + + return cci_check_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cc_open (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_result err = ccNoError; + cc_ccache_t ccache = NULL; + cc_uint32 compat_version; + cc_uint32 real_version; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &compat_version); + } + + if (!err) { + err = ccapi_context_open_ccache (in_context, in_name, &ccache); + } + + /* We must not allow a CCAPI v2 caller to open a v5-only ccache + as a v4 ccache and vice versa. Allowing that would break + (valid) assumptions made by CCAPI v2 callers. */ + + if (!err) { + err = ccapi_ccache_get_credentials_version (ccache, &real_version); + } + + if (!err) { + /* check the version and set up the ccache to use it */ + if (compat_version & real_version) { + err = cci_ccache_set_compat_version (ccache, compat_version); + } else { + err = ccErrBadCredentialsVersion; + } + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_create (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_result err = ccNoError; + cc_ccache_t ccache = NULL; + cc_uint32 compat_version; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &compat_version); + } + + if (!err) { + err = ccapi_context_create_ccache (in_context, in_name, compat_version, + in_principal, &ccache); + } + + if (!err) { + err = cci_ccache_set_compat_version (ccache, compat_version); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_close (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_release (*io_ccache); + } + + if (!err) { + *io_ccache = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_destroy (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_destroy (*io_ccache); + } + + if (!err) { + *io_ccache = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_name (apiCB *in_context, + ccache_p *in_ccache, + char **out_name) +{ + cc_result err = ccNoError; + cc_string_t name = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_get_name (in_ccache, &name); + } + + if (!err) { + char *string = strdup (name->data); + if (string) { + *out_name = string; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (name) { ccapi_string_release (name); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_cred_version (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version) +{ + cc_result err = ccNoError; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version (in_ccache, &compat_version); + } + + if (!err) { + if (compat_version == cc_credentials_v4) { + *out_version = CC_CRED_V4; + + } else if (compat_version == cc_credentials_v5) { + *out_version = CC_CRED_V5; + + } else { + err = ccErrBadCredentialsVersion; + } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_set_principal (apiCB *in_context, + ccache_p *io_ccache, + cc_int32 in_version, + char *in_principal) +{ + cc_result err = ccNoError; + cc_uint32 version; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &version); + } + + if (!err) { + err = cci_ccache_get_compat_version (io_ccache, &compat_version); + } + + if (!err && version != compat_version) { + err = cci_check_error (ccErrBadCredentialsVersion); + } + + if (!err) { + err = ccapi_ccache_set_principal (io_ccache, version, in_principal); + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_principal (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal) +{ + cc_result err = ccNoError; + cc_uint32 compat_version; + cc_string_t principal = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version (in_ccache, &compat_version); + } + + if (!err) { + err = ccapi_ccache_get_principal (in_ccache, compat_version, &principal); + } + + if (!err) { + char *string = strdup (principal->data); + if (string) { + *out_principal = string; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (principal) { ccapi_string_release (principal); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_store (apiCB *in_context, + ccache_p *io_ccache, + cred_union in_credentials) +{ + cc_result err = ccNoError; + cc_credentials_union *creds_union = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_cred_union_to_credentials_union (&in_credentials, + &creds_union); + } + + if (!err) { + err = ccapi_ccache_store_credentials (io_ccache, creds_union); + } + + if (creds_union) { cci_credentials_union_release (creds_union); } + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_remove_cred (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = NULL; + cc_uint32 found = 0; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_new_credentials_iterator (in_ccache, &iterator); + } + + while (!err && !found) { + cc_credentials_t creds = NULL; + + err = ccapi_credentials_iterator_next (iterator, &creds); + + if (!err) { + err = cci_cred_union_compare_to_credentials_union (&in_credentials, + creds->data, + &found); + } + + if (!err && found) { + err = ccapi_ccache_remove_credentials (in_ccache, creds); + } + + ccapi_credentials_release (creds); + } + if (err == ccIteratorEnd) { err = cci_check_error (ccErrCredentialsNotFound); } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_begin (apiCB *in_context, + ccache_cit **out_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_new_ccache_iterator (in_context, &iterator); + } + + if (!err) { + *out_iterator = (ccache_cit *) iterator; + iterator = NULL; /* take ownership */ + } + + if (iterator) { ccapi_ccache_iterator_release (iterator); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_next (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) in_iterator; + cc_ccache_t ccache = NULL; + const char *saved_ccache_name; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + /* CCache iterators need to return some ccaches twice (when v3 ccache has + * two kinds of credentials). To do that, we return such ccaches twice + * v4 first, then v5. */ + + if (!err) { + err = cci_ccache_iterator_get_saved_ccache_name (iterator, + &saved_ccache_name); + } + + if (!err) { + if (saved_ccache_name) { + err = ccapi_context_open_ccache (in_context, saved_ccache_name, + &ccache); + + if (!err) { + err = cci_ccache_set_compat_version (ccache, cc_credentials_v5); + } + + if (!err) { + err = cci_ccache_iterator_set_saved_ccache_name (iterator, NULL); + } + + } else { + cc_uint32 version = 0; + + err = ccapi_ccache_iterator_next (iterator, &ccache); + + if (!err) { + err = ccapi_ccache_get_credentials_version (ccache, &version); + } + + if (!err) { + if (version == cc_credentials_v4_v5) { + cc_string_t name = NULL; + + err = cci_ccache_set_compat_version (ccache, cc_credentials_v4); + + if (!err) { + err = ccapi_ccache_get_name (ccache, &name); + } + + if (!err) { + err = cci_ccache_iterator_set_saved_ccache_name (iterator, + name->data); + } + + if (name) { ccapi_string_release (name); } + + } else { + err = cci_ccache_set_compat_version (ccache, version); + } + } + } + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; /* take ownership */ + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_end (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) *io_iterator; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_iterator_release (iterator); + } + + if (!err) { + *io_iterator = NULL; + } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_begin (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = NULL; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version ((cc_ccache_t) in_ccache, + &compat_version); + } + + if (!err) { + err = ccapi_ccache_new_credentials_iterator ((cc_ccache_t) in_ccache, + &iterator); + } + + if (!err) { + err = cci_credentials_iterator_set_compat_version (iterator, + compat_version); + } + + if (!err) { + *out_iterator = (ccache_cit *) iterator; + iterator = NULL; /* take ownership */ + } + + if (iterator) { ccapi_credentials_iterator_release (iterator); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_next (apiCB *in_context, + cred_union **out_creds, + ccache_cit *in_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) in_iterator; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_creds ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_credentials_iterator_get_compat_version (iterator, + &compat_version); + } + + while (!err) { + cc_credentials_t credentials = NULL; + + err = ccapi_credentials_iterator_next (iterator, &credentials); + + if (!err && (credentials->data->version & compat_version)) { + /* got the next credentials for the correct version */ + err = cci_credentials_union_to_cred_union (credentials->data, + out_creds); + break; + } + + if (credentials) { ccapi_credentials_release (credentials); } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_end (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) *io_iterator; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_credentials_iterator_release (iterator); + } + + if (!err) { + *io_iterator = NULL; + } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_principal (apiCB *in_context, + char **io_principal) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + free (*io_principal); + *io_principal = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_name (apiCB *in_context, + char **io_name) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + free (*io_name); + *io_name = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_creds (apiCB *in_context, + cred_union **io_credentials) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_credentials) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_cred_union_release (*io_credentials); + if (!err) { *io_credentials = NULL; } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_NC_info (apiCB *in_context, + infoNC ***io_info) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_info ) { err = cci_check_error (ccErrBadParam); } + + if (!err && *io_info) { + infoNC **data = *io_info; + int i; + + for (i = 0; data[i] != NULL; i++) { + cc_free_principal (in_context, &data[i]->principal); + cc_free_name (in_context, &data[i]->name); + free (data[i]); + } + free (data); + + *io_info = NULL; + } + + return cci_remap_error (err); +} diff --git a/krb5-1-7/src/ccapi/lib/ccapi_v2.exports b/krb5-1-7/src/ccapi/lib/ccapi_v2.exports new file mode 100644 index 000000000..efa9fcec7 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/ccapi_v2.exports @@ -0,0 +1,23 @@ +cc_shutdown +cc_create +cc_close +cc_destroy +cc_get_change_time +cc_open +cc_store +cc_remove_cred +cc_set_principal +cc_get_principal +cc_get_cred_version +cc_get_name +cc_seq_fetch_NCs_begin +cc_seq_fetch_NCs_next +cc_seq_fetch_NCs_end +cc_seq_fetch_creds_begin +cc_seq_fetch_creds_next +cc_seq_fetch_creds_end +cc_get_NC_info +cc_free_principal +cc_free_name +cc_free_creds +cc_free_NC_info diff --git a/krb5-1-7/src/ccapi/lib/mac/ccapi_os_ipc.c b/krb5-1-7/src/ccapi/lib/mac/ccapi_os_ipc.c new file mode 100644 index 000000000..e0a81d878 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/mac/ccapi_os_ipc.c @@ -0,0 +1,59 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_os_ipc.h" + +#include "k5_mig_client.h" + +#define cci_server_bundle_id "edu.mit.Kerberos.CCacheServer" + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc_thread_init (void) +{ + /* k5_ipc_send_request handles all thread data for us */ + return 0; +} + +/* ------------------------------------------------------------------------ */ + +void cci_os_ipc_thread_fini (void) +{ + /* k5_ipc_send_request handles all thread data for us */ + return; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream) +{ + return cci_check_error (k5_ipc_send_request (cci_server_bundle_id, + in_launch_server, + in_request_stream, + out_reply_stream)); +} diff --git a/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.c b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.c new file mode 100644 index 000000000..ea749c089 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.c @@ -0,0 +1,839 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccapi_vector.h" + +#include "ccapi_context.h" +#include "ccapi_string.h" +#include "ccapi_ccache.h" +#include "ccapi_credentials.h" +#include "ccapi_ccache_iterator.h" +#include "ccapi_credentials_iterator.h" + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_string_functions (cc_string_t io_string) +{ + cc_string_f temp = *(io_string->functions); + *((cc_string_f *)io_string->functions) = *(io_string->vector_functions); + *((cc_string_f *)io_string->vector_functions) = temp; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_context_functions (cc_context_t io_context) +{ + cc_context_f temp = *(io_context->functions); + *((cc_context_f *)io_context->functions) = *(io_context->vector_functions); + *((cc_context_f *)io_context->vector_functions) = temp; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_ccache_functions (cc_ccache_t io_ccache) +{ + cc_ccache_f temp = *(io_ccache->functions); + *((cc_ccache_f *)io_ccache->functions) = *(io_ccache->vector_functions); + *((cc_ccache_f *)io_ccache->vector_functions) = temp; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_credentials_functions (cc_credentials_t io_credentials) +{ + cc_credentials_f temp = *(io_credentials->functions); + *((cc_credentials_f *)io_credentials->functions) = *(io_credentials->otherFunctions); + *((cc_credentials_f *)io_credentials->otherFunctions) = temp; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_ccache_iterator_functions (cc_ccache_iterator_t io_ccache_iterator) +{ + cc_ccache_iterator_f temp = *(io_ccache_iterator->functions); + *((cc_ccache_iterator_f *)io_ccache_iterator->functions) = *(io_ccache_iterator->vector_functions); + *((cc_ccache_iterator_f *)io_ccache_iterator->vector_functions) = temp; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_swap_credentials_iterator_functions (cc_credentials_iterator_t io_credentials_iterator) +{ + cc_credentials_iterator_f temp = *(io_credentials_iterator->functions); + *((cc_credentials_iterator_f *)io_credentials_iterator->functions) = *(io_credentials_iterator->vector_functions); + *((cc_credentials_iterator_f *)io_credentials_iterator->vector_functions) = temp; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_initialize_vector (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor) +{ + return cc_initialize (out_context, in_version, out_supported_version, out_vendor); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_string_release_vector (cc_string_t in_string) +{ + cci_swap_string_functions (in_string); + return ccapi_string_release (in_string); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_release_vector (cc_context_t io_context) +{ + cci_swap_context_functions (io_context); + return ccapi_context_release (io_context); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_get_change_time_vector (cc_context_t in_context, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_get_change_time (in_context, out_change_time); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t in_context, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_get_default_ccache_name (in_context, out_name); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_open_ccache_vector (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_open_ccache (in_context, in_name, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_open_default_ccache_vector (cc_context_t in_context, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_open_default_ccache (in_context, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_create_ccache_vector (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_create_ccache (in_context, in_name, in_cred_vers, in_principal, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_create_default_ccache_vector (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_create_default_ccache (in_context, in_cred_vers, in_principal, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_create_new_ccache (in_context, in_cred_vers, in_principal, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_new_ccache_iterator (in_context, out_iterator); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_lock_vector (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_lock (in_context, in_lock_type, in_block); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_unlock_vector (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_unlock (in_context); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_context_compare_vector (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = ccapi_context_compare (in_context, in_compare_to_context, out_equal); + cci_swap_context_functions (in_context); + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache) +{ + cci_swap_ccache_functions (io_ccache); + return ccapi_ccache_release (io_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache) +{ + cci_swap_ccache_functions (io_ccache); + return ccapi_ccache_destroy (io_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + err = ccapi_ccache_set_default (io_ccache); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_get_credentials_version (in_ccache, out_credentials_version); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_get_name_vector (cc_ccache_t in_ccache, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_get_name (in_ccache, out_name); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_get_principal (in_ccache, in_credentials_version, out_principal); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + err = ccapi_ccache_set_principal (io_ccache, in_credentials_version, in_principal); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + err = ccapi_ccache_store_credentials (io_ccache, in_credentials_union); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t io_ccache, + cc_credentials_t in_credentials) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + cci_swap_credentials_functions (in_credentials); + err = ccapi_ccache_remove_credentials (io_ccache, in_credentials); + cci_swap_ccache_functions (io_ccache); + cci_swap_credentials_functions (in_credentials); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_new_credentials_iterator (in_ccache, out_credentials_iterator); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_source_ccache); + cci_swap_ccache_functions (io_destination_ccache); + err = ccapi_ccache_move (io_source_ccache, io_destination_ccache); + cci_swap_ccache_functions (io_source_ccache); + cci_swap_ccache_functions (io_destination_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + err = ccapi_ccache_lock (io_ccache, in_lock_type, in_block); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (io_ccache); + err = ccapi_ccache_unlock (io_ccache); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_get_last_default_time (in_ccache, out_last_default_time); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t in_ccache, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + err = ccapi_ccache_get_change_time (in_ccache, out_change_time); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_compare_vector (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_functions (in_ccache); + cci_swap_ccache_functions (in_compare_to_ccache); + err = ccapi_ccache_compare (in_ccache, in_compare_to_ccache, out_equal); + cci_swap_ccache_functions (in_ccache); + cci_swap_ccache_functions (in_compare_to_ccache); + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials) +{ + cci_swap_credentials_functions (io_credentials); + return ccapi_credentials_release (io_credentials); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_credentials_compare_vector (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_swap_credentials_functions (in_credentials); + cci_swap_credentials_functions (in_compare_to_credentials); + err = ccapi_credentials_compare (in_credentials, in_compare_to_credentials, out_equal); + cci_swap_credentials_functions (in_credentials); + cci_swap_credentials_functions (in_compare_to_credentials); + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator) +{ + cci_swap_ccache_iterator_functions (io_ccache_iterator); + return ccapi_ccache_iterator_release (io_ccache_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_ccache_iterator_functions (in_ccache_iterator); + err = ccapi_ccache_iterator_next (in_ccache_iterator, out_ccache); + cci_swap_ccache_iterator_functions (in_ccache_iterator); + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator) +{ + cci_swap_credentials_iterator_functions (io_credentials_iterator); + return ccapi_credentials_iterator_release (io_credentials_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials) +{ + cc_int32 err = ccNoError; + cci_swap_credentials_iterator_functions (in_credentials_iterator); + err = ccapi_credentials_iterator_next (in_credentials_iterator, out_credentials); + cci_swap_credentials_iterator_functions (in_credentials_iterator); + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_shutdown_vector (apiCB **io_context) +{ + cci_swap_context_functions (*io_context); + return cc_shutdown (io_context); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_get_NC_info_vector (apiCB *in_context, + infoNC ***out_info) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_get_NC_info (in_context, out_info); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_get_change_time_vector (apiCB *in_context, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_get_change_time (in_context, out_change_time); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_open_vector (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_open (in_context, in_name, in_version, in_flags, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_create_vector (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_create (in_context, in_name, in_principal, in_version, in_flags, out_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_close_vector (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (*io_ccache); + err = cc_close (in_context, io_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_destroy_vector (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (*io_ccache); + err = cc_destroy (in_context, io_ccache); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB *in_context, + ccache_cit **out_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_seq_fetch_NCs_begin (in_context, out_iterator); + cci_swap_context_functions (in_context); + return err; +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator); + err = cc_seq_fetch_NCs_next (in_context, out_ccache, in_iterator); + cci_swap_context_functions (in_context); + cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_iterator_functions ((ccache_cit_ccache *) *io_iterator); + err = cc_seq_fetch_NCs_end (in_context, io_iterator); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_get_name_vector (apiCB *in_context, + ccache_p *in_ccache, + char **out_name) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + err = cc_get_name (in_context, in_ccache, out_name); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_get_cred_version_vector (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + err = cc_get_cred_version (in_context, in_ccache, out_version); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_set_principal_vector (apiCB *in_context, + ccache_p *io_ccache, + cc_int32 in_version, + char *in_principal) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (io_ccache); + err = cc_set_principal (in_context, io_ccache, in_version, in_principal); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_get_principal_vector (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + err = cc_get_principal (in_context, in_ccache, out_principal); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_store_vector (apiCB *in_context, + ccache_p *io_ccache, + cred_union in_credentials) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (io_ccache); + err = cc_store (in_context, io_ccache, in_credentials); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (io_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_remove_cred_vector (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + err = cc_remove_cred (in_context, in_ccache, in_credentials); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions (in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_ccache_functions ((ccache_p *)in_ccache); + err = cc_seq_fetch_creds_begin (in_context, in_ccache, out_iterator); + cci_swap_context_functions (in_context); + cci_swap_ccache_functions ((ccache_p *)in_ccache); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_creds_next_vector (apiCB *in_context, + cred_union **out_creds, + ccache_cit *in_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator); + err = cc_seq_fetch_creds_next (in_context, out_creds, in_iterator); + cci_swap_context_functions (in_context); + cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_seq_fetch_creds_end_vector (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + cci_swap_credentials_iterator_functions ((ccache_cit_creds *) *io_iterator); + err = cc_seq_fetch_creds_end (in_context, io_iterator); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_free_principal_vector (apiCB *in_context, + char **io_principal) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_free_principal (in_context, io_principal); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_free_name_vector (apiCB *in_context, + char **io_name) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_free_name (in_context, io_name); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_free_creds_vector (apiCB *in_context, + cred_union **io_credentials) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_free_creds (in_context, io_credentials); + cci_swap_context_functions (in_context); + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 __cc_free_NC_info_vector (apiCB *in_context, + infoNC ***io_info) +{ + cc_int32 err = ccNoError; + cci_swap_context_functions (in_context); + err = cc_free_NC_info (in_context, io_info); + cci_swap_context_functions (in_context); + return err; +} diff --git a/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.exports b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.exports new file mode 100644 index 000000000..0f02e4148 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.exports @@ -0,0 +1,59 @@ +__cc_context_release_vector +__cc_context_get_change_time_vector +__cc_context_get_default_ccache_name_vector +__cc_context_open_ccache_vector +__cc_context_open_default_ccache_vector +__cc_context_create_ccache_vector +__cc_context_create_default_ccache_vector +__cc_context_create_new_ccache_vector +__cc_context_new_ccache_iterator_vector +__cc_context_lock_vector +__cc_context_unlock_vector +__cc_context_compare_vector +__cc_ccache_release_vector +__cc_ccache_destroy_vector +__cc_ccache_set_default_vector +__cc_ccache_get_credentials_version_vector +__cc_ccache_get_name_vector +__cc_ccache_get_principal_vector +__cc_ccache_set_principal_vector +__cc_ccache_store_credentials_vector +__cc_ccache_remove_credentials_vector +__cc_ccache_new_credentials_iterator_vector +__cc_ccache_move_vector +__cc_ccache_lock_vector +__cc_ccache_unlock_vector +__cc_ccache_get_last_default_time_vector +__cc_ccache_get_change_time_vector +__cc_ccache_compare_vector +__cc_string_release_vector +__cc_credentials_release_vector +__cc_credentials_compare_vector +__cc_ccache_iterator_release_vector +__cc_ccache_iterator_next_vector +__cc_credentials_iterator_release_vector +__cc_credentials_iterator_next_vector +__cc_initialize_vector +__cc_shutdown_vector +__cc_get_NC_info_vector +__cc_get_change_time_vector +__cc_open_vector +__cc_create_vector +__cc_close_vector +__cc_destroy_vector +__cc_seq_fetch_NCs_begin_vector +__cc_seq_fetch_NCs_next_vector +__cc_seq_fetch_NCs_end_vector +__cc_get_name_vector +__cc_get_cred_version_vector +__cc_set_principal_vector +__cc_get_principal_vector +__cc_store_vector +__cc_remove_cred_vector +__cc_seq_fetch_creds_begin_vector +__cc_seq_fetch_creds_next_vector +__cc_seq_fetch_creds_end_vector +__cc_free_principal_vector +__cc_free_name_vector +__cc_free_creds_vector +__cc_free_NC_info_vector diff --git a/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.h b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.h new file mode 100644 index 000000000..80840f111 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/mac/ccapi_vector.h @@ -0,0 +1,228 @@ +/* + * $Header$ + * + * 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. + */ + +#include + + +cc_int32 __cc_initialize_vector (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor); + +cc_int32 __cc_string_release_vector (cc_string_t in_string); + +cc_int32 __cc_context_release_vector (cc_context_t io_context); + +cc_int32 __cc_context_get_change_time_vector (cc_context_t in_context, + cc_time_t *out_change_time); + +cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t in_context, + cc_string_t *out_name); + +cc_int32 __cc_context_open_ccache_vector (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache); + +cc_int32 __cc_context_open_default_ccache_vector (cc_context_t in_context, + cc_ccache_t *out_ccache); + +cc_int32 __cc_context_create_ccache_vector (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 __cc_context_create_default_ccache_vector (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator); + +cc_int32 __cc_context_lock_vector (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 __cc_context_unlock_vector (cc_context_t in_context); + +cc_int32 __cc_context_compare_vector (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal); + +cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache); + +cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache); + +cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache); + +cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version); + +cc_int32 __cc_ccache_get_name_vector (cc_ccache_t in_ccache, + cc_string_t *out_name); + +cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal); + +cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal); + +cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union); + +cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t io_ccache, + cc_credentials_t in_credentials); + +cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator); + +cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache); + +cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache); + +cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time); + +cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t in_ccache, + cc_time_t *out_change_time); + +cc_int32 __cc_ccache_compare_vector (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal); + +cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials); + +cc_int32 __cc_credentials_compare_vector (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal); + +cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator); + +cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache); + +cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator); + +cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials); + +cc_int32 __cc_shutdown_vector (apiCB **io_context); + +cc_int32 __cc_get_NC_info_vector (apiCB *in_context, + infoNC ***out_info); + +cc_int32 __cc_get_change_time_vector (apiCB *in_context, + cc_time_t *out_change_time); + +cc_int32 __cc_open_vector (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache); + +cc_int32 __cc_create_vector (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache); + +cc_int32 __cc_close_vector (apiCB *in_context, + ccache_p **io_ccache); + +cc_int32 __cc_destroy_vector (apiCB *in_context, + ccache_p **io_ccache); + +cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB *in_context, + ccache_cit **out_iterator); + +cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_iterator); + +cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB *in_context, + ccache_cit **io_iterator); + +cc_int32 __cc_get_name_vector (apiCB *in_context, + ccache_p *in_ccache, + char **out_name); + +cc_int32 __cc_get_cred_version_vector (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version); + +cc_int32 __cc_set_principal_vector (apiCB *in_context, + ccache_p *io_ccache, + cc_int32 in_version, + char *in_principal); + +cc_int32 __cc_get_principal_vector (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal); + +cc_int32 __cc_store_vector (apiCB *in_context, + ccache_p *io_ccache, + cred_union in_credentials); + +cc_int32 __cc_remove_cred_vector (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials); + +cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_iterator); + +cc_int32 __cc_seq_fetch_creds_next_vector (apiCB *in_context, + cred_union **out_creds, + ccache_cit *in_iterator); + +cc_int32 __cc_seq_fetch_creds_end_vector (apiCB *in_context, + ccache_cit **io_iterator); + +cc_int32 __cc_free_principal_vector (apiCB *in_context, + char **io_principal); + +cc_int32 __cc_free_name_vector (apiCB *in_context, + char **io_name); + +cc_int32 __cc_free_creds_vector (apiCB *in_context, + cred_union **io_credentials); + +cc_int32 __cc_free_NC_info_vector (apiCB *in_context, + infoNC ***io_info); diff --git a/krb5-1-7/src/ccapi/lib/unix/Makefile.in b/krb5-1-7/src/ccapi/lib/unix/Makefile.in new file mode 100644 index 000000000..2651fad39 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/unix/Makefile.in @@ -0,0 +1,11 @@ +thisconfigdir=../../.. +myfulldir=ccapi/lib/unix +mydir=ccapi/lib/unix +BUILDTOP=$(REL)..$(S)..$(S).. + +all-unix:: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + +# +++ Dependency line eater +++ diff --git a/krb5-1-7/src/ccapi/lib/win/Makefile.in b/krb5-1-7/src/ccapi/lib/win/Makefile.in new file mode 100644 index 000000000..df4d95fd9 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/Makefile.in @@ -0,0 +1,119 @@ +# makefile: Constructs the Kerberos for Windows CCAPI DLL. +# +OBJS = $(OUTPRE)ccapi_ccache.obj \ + $(OUTPRE)ccapi_ccache_iterator.obj \ + $(OUTPRE)ccapi_context.obj \ + $(OUTPRE)ccapi_context_change_time.obj \ + $(OUTPRE)ccapi_credentials.obj \ + $(OUTPRE)ccapi_credentials_iterator.obj \ + $(OUTPRE)ccapi_ipc.obj \ + $(OUTPRE)ccapi_os_ipc.obj \ + $(OUTPRE)ccapi_string.obj \ + $(OUTPRE)ccapi_v2.obj \ + $(OUTPRE)cci_array_internal.obj \ + $(OUTPRE)cci_cred_union.obj \ + $(OUTPRE)cci_debugging.obj \ + $(OUTPRE)cci_identifier.obj \ + $(OUTPRE)cci_message.obj \ + $(OUTPRE)cci_os_debugging.obj \ + $(OUTPRE)cci_os_identifier.obj \ + $(OUTPRE)cci_stream.obj \ + $(OUTPRE)ccs_reply_proc.obj \ + $(OUTPRE)ccs_reply_s.obj \ + $(OUTPRE)ccs_request_c.obj \ + $(OUTPRE)ccutils.obj \ + $(OUTPRE)client.obj \ + $(OUTPRE)dllmain.obj \ + $(OUTPRE)init.obj \ + $(OUTPRE)rpc.obj \ + $(OUTPRE)secure.obj \ + $(OUTPRE)tls.obj \ + $(OUTPRE)util.obj \ + $(OUTPRE)win-utils.obj + +##### Options +# Set NODEBUG if building release instead of debug + +#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/lib/win, for making Makefile. +BUILDTOP=..\..\..\ +CCAPI = $(BUILDTOP)\CCAPI +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +LIBDIR = $(CCAPI)\lib +LIBWIN = $(LIBDIR)\win +POSIX = $(BUILDTOP)\lib\krb5\posix +OLDCC = $(LIBWIN)\OldCC +SRCTMP = $(LIBWIN)\srctmp + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +# Because all the sources are pulled together into the temp directory SRCTMP, +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \ + -I..\$(BUILDTOP)\util\et +MIDLINCLUDES = /I..\$(BUILDTOP)\include + +CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS $(cvarsdll) + + +##### Linker +LINK = link +LIBS = kernel32.lib ws2_32.lib user32.lib advapi32.lib +LFLAGS = /nologo $(LOPTS) + +all:: Makefile copysrc midl $(OUTPRE)ccapi.dll finish + +ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_reply.idl + +copysrc : + echo "Copying all sources needed to build ccapi.dll to $(SRCTMP)" + if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP) + xcopy /D/Y $(CO)\*.* $(SRCTMP) + xcopy /D/Y $(COWIN)\*.* $(SRCTMP) + xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP) + xcopy /D/Y $(LIBDIR)\*.* $(SRCTMP) + xcopy /D/Y $(LIBWIN)\*.* $(SRCTMP) + xcopy /D/Y $(OLDCC)\*.* $(SRCTMP) + cd $(SRCTMP) + if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE) + +midl : ccs_request.h ccs_reply.h + +# Main program: +$(OUTPRE)ccapi.dll: $(OBJS) ccapi.def + $(LINK) $(LFLAGS) -entry:_DllMainCRTStartup@12 -dll /map:$*.map /out:$@ /DEF:ccapi.def $(OBJS) \ + /implib:ccapi.lib $(dllflags) $(LIBS) $(KFWLIB) $(SCLIB) rpcrt4.lib $(conlibsdll) $(conflags) + +ccapi.def: + echo ;ccapi.def is generated by a Makefile rule. > ccapi.def + echo HEAPSIZE 8192 >> ccapi.def + echo EXPORTS >> ccapi.def + type ccapi.exports >> ccapi.def + type ccapi_v2.exports >> ccapi.def + type debug.exports >> ccapi.def + +finish: + echo "Finished in ccapi/lib/win." + cd .. + +install:: + echo "Doing nothing for make install" + +clean:: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.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 + if exist $(SRCTMP) rm -rf $(SRCTMP) \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/lib/win/OldCC/ccapi.h b/krb5-1-7/src/ccapi/lib/win/OldCC/ccapi.h new file mode 100644 index 000000000..c40bd1158 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/OldCC/ccapi.h @@ -0,0 +1,284 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Fri Nov 30 10:06:16 2007 + */ +/* Compiler settings for ccapi.idl: + Oic, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, oldnames + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __ccapi_h__ +#define __ccapi_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +#ifndef __ccapi_INTERFACE_DEFINED__ +#define __ccapi_INTERFACE_DEFINED__ + +/* interface ccapi */ +/* [implicit_handle][unique][version][uuid] */ + +typedef /* [context_handle] */ struct opaque_handle_CTX *HCTX; + +typedef /* [context_handle] */ struct opaque_handle_CACHE *HCACHE; + +typedef /* [context_handle] */ struct opaque_handle_CACHE_ITER *HCACHE_ITER; + +typedef /* [context_handle] */ struct opaque_handle_CRED_ITER *HCRED_ITER; + +typedef unsigned char CC_CHAR; + +typedef unsigned char CC_UCHAR; + +typedef int CC_INT32; + +typedef unsigned int CC_UINT32; + +typedef CC_INT32 CC_TIME_T; + + +enum __MIDL_ccapi_0001 + { STK_AFS = 0, + STK_DES = 1 + } ; + +enum __MIDL_ccapi_0002 + { CC_API_VER_1 = 1, + CC_API_VER_2 = 2 + } ; + +enum __MIDL_ccapi_0003 + { KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40, + MAX_V4_CRED_LEN = 1250 + } ; +typedef struct _NC_INFO + { + /* [string] */ CC_CHAR *name; + /* [string] */ CC_CHAR *principal; + CC_INT32 vers; + } NC_INFO; + +typedef struct _NC_INFO_LIST + { + CC_UINT32 length; + /* [size_is] */ NC_INFO *info; + } NC_INFO_LIST; + +typedef struct _V4_CRED + { + CC_UCHAR kversion; + CC_CHAR principal[ 41 ]; + CC_CHAR principal_instance[ 41 ]; + CC_CHAR service[ 41 ]; + CC_CHAR service_instance[ 41 ]; + CC_CHAR realm[ 41 ]; + CC_UCHAR session_key[ 8 ]; + CC_INT32 kvno; + CC_INT32 str_to_key; + CC_INT32 issue_date; + CC_INT32 lifetime; + CC_UINT32 address; + CC_INT32 ticket_sz; + CC_UCHAR ticket[ 1250 ]; + } V4_CRED; + +typedef struct _CC_DATA + { + CC_UINT32 type; + CC_UINT32 length; + /* [size_is] */ CC_UCHAR *data; + } CC_DATA; + +typedef struct _CC_DATA_LIST + { + CC_UINT32 count; + /* [size_is] */ CC_DATA *data; + } CC_DATA_LIST; + +typedef struct _V5_CRED + { + /* [string] */ CC_CHAR *client; + /* [string] */ CC_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_LIST addresses; + CC_DATA ticket; + CC_DATA second_ticket; + CC_DATA_LIST authdata; + } V5_CRED; + +typedef /* [switch_type] */ union _CRED_PTR_UNION + { + /* [case()] */ V4_CRED *pV4Cred; + /* [case()] */ V5_CRED *pV5Cred; + } CRED_PTR_UNION; + +typedef struct _CRED_UNION + { + CC_INT32 cred_type; + /* [switch_is] */ CRED_PTR_UNION cred; + } CRED_UNION; + +CC_INT32 rcc_initialize( + /* [out] */ HCTX *pctx); + +CC_INT32 rcc_shutdown( + /* [out][in] */ HCTX *pctx); + +CC_INT32 rcc_get_change_time( + /* [in] */ HCTX ctx, + /* [out] */ CC_TIME_T *time); + +CC_INT32 rcc_create( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [string][in] */ const CC_CHAR *principal, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_open( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_close( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_destroy( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs_begin( + /* [in] */ HCTX ctx, + /* [out] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_end( + /* [out][in] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_next( + /* [in] */ HCACHE_ITER iter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs( + /* [in] */ HCTX ctx, + /* [out][in] */ HCACHE_ITER *piter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_get_NC_info( + /* [in] */ HCTX ctx, + /* [out] */ NC_INFO_LIST **info_list); + +CC_INT32 rcc_get_name( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **name); + +CC_INT32 rcc_set_principal( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 vers, + /* [string][in] */ const CC_CHAR *principal); + +CC_INT32 rcc_get_principal( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **principal); + +CC_INT32 rcc_get_cred_version( + /* [in] */ HCACHE cache, + /* [out] */ CC_INT32 *vers); + +CC_INT32 rcc_lock_request( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 lock_type); + +CC_INT32 rcc_store( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_remove_cred( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_seq_fetch_creds( + /* [in] */ HCACHE cache, + /* [out][in] */ HCRED_ITER *piter, + /* [out] */ CRED_UNION **cred); + +CC_INT32 rcc_seq_fetch_creds_begin( + /* [in] */ HCACHE cache, + /* [out] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_end( + /* [out][in] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_next( + /* [in] */ HCRED_ITER iter, + /* [out] */ CRED_UNION **cred); + +CC_UINT32 Connect( + /* [string][in] */ CC_CHAR *name); + +void Shutdown( void); + + +extern handle_t ccapi_IfHandle; + + +extern RPC_IF_HANDLE ccapi_ClientIfHandle; +extern RPC_IF_HANDLE ccapi_ServerIfHandle; +#endif /* __ccapi_INTERFACE_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +void __RPC_USER HCTX_rundown( HCTX ); +void __RPC_USER HCACHE_rundown( HCACHE ); +void __RPC_USER HCACHE_ITER_rundown( HCACHE_ITER ); +void __RPC_USER HCRED_ITER_rundown( HCRED_ITER ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/krb5-1-7/src/ccapi/lib/win/OldCC/client.cxx b/krb5-1-7/src/ccapi/lib/win/OldCC/client.cxx new file mode 100644 index 000000000..ed8712339 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/OldCC/client.cxx @@ -0,0 +1,389 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" // KPKDBG + +#include "ccs_request.h" + +#include "ccapi.h" +#include "util.h" + +extern "C" { +#include "cci_debugging.h" +#include "tls.h" // KPKDBG + } + +#include "client.h" +#include "init.hxx" +#include "name.h" +#include "secure.hxx" + +#define SECONDS_TO_WAIT 10 + +#define STARTUP "CLIENT STARTUP: " +#define DISCONNECT "CLIENT DISCONNECT: " + +bool Client::s_init = false; +CcOsLock Client::sLock; + +static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) { + DWORD status = 0; + unsigned char * pszStringBinding = NULL; + + if (!ep) { + status = alloc_name(endpoint, "ep", isNT()); + } + else { + *endpoint = ep; + } + + if (!status) { + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(0, // uuid + (unsigned char*)"ncalrpc", // protseq + 0, // address + (unsigned char*)(*endpoint), // endpoint + 0, // options + &pszStringBinding); + cci_check_error(status); + } + + if (!status) { + /* Set the binding handle that will be used to bind to the server. */ + status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle); + cci_check_error(status); + } + + if (!status) { + // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not + // quite work on Win9x... + if (isNT()) { + RPC_SECURITY_QOS qos; + qos.Version = RPC_C_SECURITY_QOS_VERSION; + qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; + qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; + qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; + + status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle, + 0, // principal + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + 0, // current address space + RPC_C_AUTHZ_NAME, + &qos); + cci_check_error(status); + } + } + + if (pszStringBinding) { + DWORD status = RpcStringFree(&pszStringBinding); + cci_check_error(status); + } + return cci_check_error(status); + } + +DWORD find_server(Init::InitInfo& info, LPSTR endpoint) { + DWORD status = 0; + LPSTR event_name = 0; + HANDLE hEvent = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + PSECURITY_ATTRIBUTES psa = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + char* szExe = 0; + char* szDir = 0; + BOOL bRes = FALSE; + char* cmdline = NULL; +#if 0 + HANDLE hToken = 0; +#endif + + psa = isNT() ? &sa : 0; + + cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle); + status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle)); + if (status == RPC_S_NOT_LISTENING) { + cci_debug_printf(" Server *NOT* found!"); + si.cb = sizeof(si); + + status = alloc_module_dir_name(CCAPI_DLL, &szDir); + + if (!status) { + status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + cci_check_error(status); + } + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + } + + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent); + if (!hEvent) status = GetLastError(); + } + + if (!status) { + +#if 0 + if (SecureClient::IsImp()) { + cci_debug_printf(STARTUP "Token is impersonation token")); + SecureClient::DuplicateImpAsPrimary(hToken); + } + else { + cci_debug_printf(STARTUP "Token is NOT impersonation token")); + } +#endif + +#if 0 + if (hToken) + bRes = CreateProcessAsUser(hToken, + szExe, // app name + NULL, // cmd line + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + //CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + DETACHED_PROCESS | + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + else +#endif + alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline); + bRes = CreateProcess( szExe, // app name + NULL, //cmdline, // cmd line is + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + // DETACHED_PROCESS | /* KPK TODO: was set - restore */ + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + if (!bRes) { + status = GetLastError(); + cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status); + } + cci_debug_printf(" Waiting..."); + } + cci_check_error(status); + + if (!status) { + status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000); + status = RpcMgmtIsServerListening(ccs_request_IfHandle); + } + } + else if (status) { + cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status); + } + +#if 0 + if (hToken) + CloseHandle(hToken); +#endif + if (szDir) free_alloc_p(&szDir); + if (szExe) free_alloc_p(&szExe); + if (hEvent) CloseHandle(hEvent); + if (pi.hThread) CloseHandle(pi.hThread); + if (pi.hProcess) CloseHandle(pi.hProcess); + if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor); + return cci_check_error(status); + +} + +static +DWORD +authenticate_server(Init::InitInfo& info) { + DWORD challenge = 17; // XXX - maybe use random number + DWORD desired_response= challenge + 1; + HANDLE hMap = 0; + LPSTR mem_name = 0; + PDWORD pvalue = 0; + CC_UINT32 response = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + + cci_debug_printf("%s entry", __FUNCTION__); + + status = alloc_name(&mem_name, "auth", isNT()); + cci_check_error(status); + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + } + } + cci_check_error(status); + + if (!status) { + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, + PAGE_READWRITE, 0, sizeof(DWORD), mem_name); + if (!hMap) + status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!pvalue) status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + *pvalue = challenge; + + RpcTryExcept { + response = ccs_authenticate( (CC_CHAR*)mem_name ); + } + RpcExcept(1) { + status = RpcExceptionCode(); + cci_check_error(status); + } + RpcEndExcept; + } + cci_check_error(status); + + if (!status) { + // Check response + if ((response != desired_response) && (*pvalue != desired_response)) { + cci_debug_printf(" Could not authenticate server."); + status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND? + } + else { + cci_debug_printf(" Server authenticated!"); + } + cci_check_error(status); + } + + free_alloc_p(&mem_name); + free_alloc_p(&sa.lpSecurityDescriptor); + if (pvalue) { + BOOL ok = UnmapViewOfFile(pvalue); +// DEBUG_ASSERT(ok); + } + if (hMap) CloseHandle(hMap); + return status; +} + +DWORD +Client::Disconnect() { + DWORD status = 0; + if (ccs_request_IfHandle) { + /* The calls to the remote procedures are complete. */ + /* Free the binding handle */ + status = RpcBindingFree(&ccs_request_IfHandle); + } + s_init = false; + return status; + } + +DWORD +Client::Connect(char* ep OPTIONAL) { + LPSTR endpoint = 0; + DWORD status = 0; + + if (!ccs_request_IfHandle) { + Init::InitInfo info; + + status = Init::Info(info); + cci_check_error(status); + + if (!status) { + status = bind_client(ep, info, &endpoint); + cci_check_error(status); + } + + if (!status) { + status = find_server(info, endpoint); + cci_check_error(status); + } + + if (!status) { + status = authenticate_server(info); + cci_check_error(status); + } + } + + + if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint); + + if (status) Client::Disconnect(); + return status; + } + +DWORD Client::Initialize(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + ccs_request_IfHandle = NULL; + if (s_init) return 0; + DWORD status = Client::Connect(ep); + if (!status) s_init = true; + return status; + } + +DWORD Client::Cleanup() { + CcAutoLock AL(Client::sLock); + SecureClient s; + return Client::Disconnect(); + } + +DWORD Client::Reconnect(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + DWORD status = 0; + + if (Initialized()) { + DWORD status = Client::Cleanup(); + } + if ( (!status) ) { + status = Client::Initialize(ep); + } + + return status; + } diff --git a/krb5-1-7/src/ccapi/lib/win/OldCC/client.h b/krb5-1-7/src/ccapi/lib/win/OldCC/client.h new file mode 100644 index 000000000..52be2edfb --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/OldCC/client.h @@ -0,0 +1,61 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 __DLL_CLIENT_H__ +#define __DLL_CLIENT_H__ + +#include "autolock.hxx" +#include "init.hxx" + +class Client { +public: + static DWORD Initialize(char* ep OPTIONAL); + static DWORD Cleanup(); + static DWORD Reconnect(char* ep OPTIONAL); + + static bool Initialized() { return s_init; } + + static CcOsLock sLock; + +private: + static bool s_init; + + static DWORD Disconnect(); + static DWORD Connect(char* ep OPTIONAL); + }; + +#define CLIENT_INIT_EX(trap, error) \ +do \ +{ \ + INIT_INIT_EX(trap, error); \ + if (!Client::Initialized()) \ + { \ + DWORD status = Client::Initialize(0); \ + if (status) return (trap) ? (error) : status; \ + } \ +} while(0) + +#endif diff --git a/krb5-1-7/src/ccapi/lib/win/OldCC/rpc.cxx b/krb5-1-7/src/ccapi/lib/win/OldCC/rpc.cxx new file mode 100644 index 000000000..29edc3c57 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/OldCC/rpc.cxx @@ -0,0 +1,79 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +extern "C" { +#include "CredentialsCache.h" +#include "secure.hxx" +#include "client.h" +#include "autolock.hxx" +#include "cci_debugging.h" + } + +extern HANDLE hCCAPIv2Mutex; + +#define MAKE_RPC_CALL(rc, x) \ +do { \ + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \ + SecureClient* s = 0; \ + SecureClient::Start(s); \ + CcAutoLock* a = 0; \ + CcAutoLock::Start(a, Client::sLock); \ + RpcTryExcept { \ + cci_debug_printf("RpcTry: #x"); \ + x; \ + } \ + RpcExcept(1) { \ + rc = handle_exception(RpcExceptionCode()); \ + } \ + RpcEndExcept; \ + CcAutoLock::Stop(a); \ + SecureClient::Stop(s); \ + ReleaseMutex( hCCAPIv2Mutex ); \ +} while (0) + +static +DWORD +handle_exception(DWORD code) { + cci_debug_printf("Runtime reported exception %u", code); + if (code == RPC_S_SERVER_UNAVAILABLE) { + Client::Reconnect(0); + } + return 4; + } + +////////////////////////////////////////////////////////////////////////////// + +cc_int32 cc_initialize() { + + CLIENT_INIT_EX(true, 4); + cc_int32 rc = ccNoError; + + MAKE_RPC_CALL(rc, rc = 5); + return rc; + } \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/lib/win/WINCCAPI.sln b/krb5-1-7/src/ccapi/lib/win/WINCCAPI.sln new file mode 100644 index 000000000..985f4c610 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/WINCCAPI.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WINCCAPI", "WINCCAPI.vcproj", "{1137FC16-E53E-48C1-8293-085B4BE68C32}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.ActiveCfg = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.Build.0 = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.ActiveCfg = Release|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1-7/src/ccapi/lib/win/WINCCAPI.vcproj b/krb5-1-7/src/ccapi/lib/win/WINCCAPI.vcproj new file mode 100644 index 000000000..69b7722e8 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/WINCCAPI.vcproj @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krb5-1-7/src/ccapi/lib/win/ccapi_os_ipc.cxx b/krb5-1-7/src/ccapi/lib/win/ccapi_os_ipc.cxx new file mode 100644 index 000000000..6ccd59b9a --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/ccapi_os_ipc.cxx @@ -0,0 +1,379 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include "k5-thread.h" +#include "ccapi_os_ipc.h" +#include "cci_debugging.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "ccutils.h" +#include "tls.h" +#include "util.h" +#include "win-utils.h" + } + +#include "autolock.hxx" +#include "CredentialsCache.h" +#include "secure.hxx" +#include "opts.hxx" +#include "client.h" + +extern "C" DWORD GetTlsIndex(); + +#define SECONDS_TO_WAIT 10 +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + +extern HANDLE hCCAPIv2Mutex; +ParseOpts::Opts opts = { 0 }; +PSECURITY_ATTRIBUTES psa = 0; +SECURITY_ATTRIBUTES sa = { 0 }; + +/* The layout of the rest of this module: + + The entrypoints defined in ccs_os_ipc.h: + cci_os_ipc_thread_init + cci_os_ipc + + Other routines needed by those four. + cci_os_connect + handle_exception + */ + +cc_int32 ccapi_connect(const struct tspdata* tsp); +static DWORD handle_exception(DWORD code); + +extern "C" { +cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + cc_int32 in_msg, + k5_ipc_stream* out_reply_stream); + } + +/* ------------------------------------------------------------------------ */ + +extern "C" cc_int32 cci_os_ipc_thread_init (void) { + cc_int32 err = ccNoError; + struct tspdata* ptspdata; + HANDLE replyEvent; + UUID __RPC_FAR uuid; + unsigned char __RPC_FAR* uuidString = NULL; + + if (!GetTspData(GetTlsIndex(), &ptspdata)) return ccErrNoMem; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + err = cci_check_error(UuidCreate(&uuid)); // Get a UUID + if (err == RPC_S_OK) { // Convert to string + err = UuidToString(&uuid, &uuidString); + } + if (!err) { // Save in thread local storage + tspdata_setUUID(ptspdata, uuidString); + } +#if 0 + cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata)); +#endif + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = Init:: Initialize( ); + if (!err) if (!Client::Initialized()) err = Client::Initialize(0); + + if (!err) { + /* Whenever a reply to an RPC request is received, the RPC caller needs to + know when the reply has been received. It does that by waiting for a + client-specific event to be set. Define the event name to be _reply: */ + replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); + } + + if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); + else err = cci_check_error(GetLastError()); + + if (uuidString) RpcStringFree(&uuidString); + + return cci_check_error(err); + } + + +/* ------------------------------------------------------------------------ */ + +void cci_os_ipc_thread_fini (void) +{ +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream* out_reply_stream) { + return cci_os_ipc_msg( in_launch_server, + in_request_stream, + CCMSG_REQUEST, + out_reply_stream); + } + +extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + cc_int32 in_msg, + k5_ipc_stream* out_reply_stream) { + + cc_int32 err = ccNoError; + cc_int32 done = FALSE; + cc_int32 try_count = 0; + cc_int32 server_died = FALSE; + TCHAR* pszStringBinding= NULL; + struct tspdata* ptspdata = NULL; + char* uuid = NULL; + int lenUUID = 0; + unsigned int trycount = 0; + time_t sst = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + HANDLE replyEvent = 0; + BOOL bCCAPI_Connected= FALSE; + + if (!in_request_stream) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;} + bCCAPI_Connected = tspdata_getConnected (ptspdata); + replyEvent = tspdata_getReplyEvent (ptspdata); + sst = tspdata_getSST (ptspdata); + uuid = tspdata_getUUID(ptspdata); + + // The lazy connection to the server has been put off as long as possible! + // ccapi_connect starts listening for replies as an RPC server and then + // calls ccs_rpc_connect. + if (!bCCAPI_Connected) { + err = cci_check_error(ccapi_connect(ptspdata)); + bCCAPI_Connected = !err; + tspdata_setConnected(ptspdata, bCCAPI_Connected); + } + + // Clear replyEvent so we can detect when a reply to our request has been received: + ResetEvent(replyEvent); + + //++ Use the old CCAPI implementation to try to talk to the server: + // It has all the code to use the RPC in a thread-safe way, make the endpoint, + // (re)connect and (re)start the server. + // Note: the old implementation wrapped the thread-safety stuff in a macro. + // Here it is expanded and thus duplicated for each RPC call. The new code has + // a very limited number of RPC calls, unlike the older code. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); + if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!err) { + RpcTryExcept { + if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;} + uuid = tspdata_getUUID(ptspdata); + lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */ +#if 0 + cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata); + cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst); +#endif + ccs_rpc_request( /* make call with user message: */ + in_msg, /* Message type */ + (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + k5_ipc_stream_size(in_request_stream), + (unsigned char*)k5_ipc_stream_data(in_request_stream), /* Data buffer */ + sst, /* session start time */ + (long*)(&err) ); /* Return code */ + } + RpcExcept(1) { + handle_exception(RpcExceptionCode()); + } + RpcEndExcept; + } + + cci_check_error(err); + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + //-- Use the old CCAPI implementation to try to talk to the server. + + // Wait for reply handler to set event: + if (!err) { + err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000)); + } + + if (!err) { + err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + } + + if (!err && server_died) { + err = cci_check_error (ccErrServerUnavailable); + } +#if 0 + if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { + err = ccNoError; /* If the server is not running just return an empty stream. */ + } +#endif + + if (!err) { + *out_reply_stream = tspdata_getStream(ptspdata); + } + + return cci_check_error (err); + } + + + +static DWORD handle_exception(DWORD code) { + cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); + if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { + Client::Reconnect(0); + } + return 4; + } + + +/* Establish a CCAPI connection with the server. + * The connect logic here is identical to the logic in the send request code. + * TODO: merge this connect code with that request code. + */ +cc_int32 ccapi_connect(const struct tspdata* tsp) { + BOOL bListen = TRUE; + char* endpoint = NULL; + HANDLE replyEvent = 0; + RPC_STATUS status = FALSE; + char* uuid = NULL; + + /* Start listening to our uuid before establishing the connection, + * so that when the server tries to call ccapi_listen, we will be ready. + */ + + /* Build complete RPC uuid using previous CCAPI implementation: */ + replyEvent = tspdata_getReplyEvent(tsp); + uuid = tspdata_getUUID(tsp); + endpoint = clientEndpoint(uuid); + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + if (!status) { + status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", + opts.cMaxCalls, + (RPC_CSTR)endpoint, + sa.lpSecurityDescriptor); // SD + cci_check_error(status); + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0 ); + cci_check_error(status); + } + + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!status) { + if (!isNT()) { + status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + opts.cMaxCalls, + NULL); // No security callback. + } + + cci_check_error(status); + + if (!status) { + status = RpcServerListen(opts.cMinCalls, + opts.cMaxCalls, + TRUE); + cci_check_error(status); + } + } + + // Clear replyEvent so we can detect when a reply to our connect request has been received: + ResetEvent(replyEvent); + + // We use the old CCAPI implementation to try to talk to the server. + // It has all the code to make the uuid, (re)connect and (re)start the server. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!status) if (!Init:: Initialized()) status = Init:: Initialize( ); + if (!status) if (!Client::Initialized()) status = Client::Initialize(0); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!status) { + RpcTryExcept { + ccs_rpc_connect( /* make call with user message: */ + CCMSG_CONNECT, /* Message type */ + (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + (long*)(&status) ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + status = ccErrBadInternalMessage; + } + RpcEndExcept; + } + + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + + if (!status) { +#if 0 + cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__); +#endif + status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000); + status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : ""); + } + if (status) { + cci_debug_printf(" unexpected error while looking for server... (%u)", status); + } + + return status; + } \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/lib/win/ccs_reply_proc.c b/krb5-1-7/src/ccapi/lib/win/ccs_reply_proc.c new file mode 100644 index 000000000..8eb340836 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/ccs_reply_proc.c @@ -0,0 +1,96 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "cci_debugging.h" +#include "ccs_reply.h" /* generated by MIDL compiler */ +#include "ccutils.h" +#include "tls.h" +#include "win-utils.h" + + +void ccs_rpc_request_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + const long cbIn, /* Length of buffer */ + const char* chIn, /* Data buffer */ + long* ret_status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + DWORD* p = (DWORD*)(tspHandle); + struct tspdata* tsp = (struct tspdata*)*p; + k5_ipc_stream stream; + long status = 0; +#if 0 + cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid); +#endif + if (!status) { + status = k5_ipc_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = k5_ipc_stream_write (stream, chIn, cbIn); + } + + if (!status) { /* Put the data into the stream */ + tspdata_setStream(tsp, stream); + } + + SetEvent(hEvent); + CloseHandle(hEvent); + *ret_status = status; + } + +void ccs_rpc_connect_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + long* status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + DWORD* p = (DWORD*)(tspHandle); +#if 0 + cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid); +#endif + SetEvent(hEvent); + CloseHandle(hEvent); + } + +void ccapi_listen( + RPC_ASYNC_STATE* rpcState, + handle_t hBinding, + const long rpcmsg, /* Message type */ + long* status ) { /* Return code */ + + cci_debug_printf("%s %s!", __FUNCTION__, rpcState->UserInfo); + *status = 0; + } diff --git a/krb5-1-7/src/ccapi/lib/win/debug.exports b/krb5-1-7/src/ccapi/lib/win/debug.exports new file mode 100644 index 000000000..d7fbcc152 --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/debug.exports @@ -0,0 +1,13 @@ + cci_debug_printf + _cci_check_error + cci_os_ipc + cci_os_ipc_msg + cci_os_ipc_thread_init + k5_ipc_stream_data + k5_ipc_stream_write + k5_ipc_stream_new + + ccs_authenticate + + + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/lib/win/dllmain.cxx b/krb5-1-7/src/ccapi/lib/win/dllmain.cxx new file mode 100644 index 000000000..e37a9ad6b --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/dllmain.cxx @@ -0,0 +1,216 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include +#include + +#include "dllmain.h" +#include "tls.h" +#include "cci_debugging.h" +#include "ccapi_context.h" +#include "client.h" + +void cci_thread_init__auxinit(); + } + + +#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") + +// Process-specific data: +static DWORD dwTlsIndex; +static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. +static HANDLE sessionToken; +static char* ep_prefices[] = {"CCS", "CCAPI"}; +HANDLE hCCAPIv2Mutex = NULL; +DWORD firstThreadID = 0; + +// These data structures are used by the old CCAPI implementation +// to keep track of the state of the RPC connection. All data is static. +static Init init; +static Client client; + +DWORD GetTlsIndex() {return dwTlsIndex;} + +// DllMain() is the entry-point function for this DLL. +BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD fdwReason, // reason called + LPVOID lpvReserved) { // reserved + + struct tspdata* ptspdata; + BOOL fIgnore; + BOOL bStatus; + DWORD status = 0; // 0 is success. + DWORD maxUN = sizeof(_user); + unsigned int i = 0; + unsigned int j = 0; + + switch (fdwReason) { + // The DLL is loading due to process initialization or a call to LoadLibrary: + case DLL_PROCESS_ATTACH: + cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); + // Process-wide mutex used to allow only one thread at a time into the RPC code: + hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); + + // Figure out our username; it's process-wide: + bStatus = GetUserName(_user, &maxUN); + if (!bStatus) return bStatus; + + // Remove any characters that aren't valid endpoint characters: + while (_user[j] != 0) { + if (isalnum(_user[j])) _user[i++] = _user[j]; + j++; + } + _user[i] = '\0'; + + // Our logon session is determined in client.cxx, old CCAPI code carried + // over to this implementation. + + // Allocate a TLS index: + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + // Initialize CCAPI once per DLL load: + firstThreadID = GetCurrentThreadId(); + + // Don't break; fallthrough: Initialize the TLS index for first thread. + + // The attached process creates a new thread: + case DLL_THREAD_ATTACH: + // Initialize the TLS index for this thread: + ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata)); + cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata); + if (ptspdata == NULL) return FALSE; + fIgnore = TlsSetValue(dwTlsIndex, ptspdata); + + memset(ptspdata, 0, sizeof(struct tspdata)); + + // Initialize CCAPI once per DLL load: + if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit(); + + break; + + // The thread of the attached process terminates: + case DLL_THREAD_DETACH: + cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) { + LocalFree((HLOCAL) ptspdata); + TlsSetValue(dwTlsIndex, NULL); + } + break; + + // DLL unload due to process termination or FreeLibrary: + case DLL_PROCESS_DETACH: + cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); + //++ Copied from previous implementation: + // Process Teardown "Problem" + // + // There are two problems that occur during process teardown: + // + // 1) Windows (NT/9x/2000) does not keep track of load/unload + // ordering dependencies for use in process teardown. + // + // 2) The RPC exception handling in the RPC calls do not work + // during process shutdown in Win9x. + // + // When a process is being torn down in Windows, the krbcc DLL + // may get a DLL_PROCESS_DETACH before other DLLs are done + // with it. Thus, it may disconnect from the RPC server + // before the last shutdown RPC call. + // + // On NT/2000, this is ok because the RPC call will fail and just + // return an error. + // + // On Win9x/Me, the RPC exception will not be caught. + // However, Win9x ignores exceptions during process shutdown, + // so the exception will never be seen unless a debugger is + // attached to the proccess. + // + // A good potential woraround would be to have a global + // variable that denotes whether the DLL is attached to the + // process. If it is not, all entrypoints into the DLL should + // return failure. + // + // A not as good workaround is below but ifdefed out. + // + // However, we can safely ignore this problem since it can + // only affects people running debuggers under 9x/Me who are + // using multiple DLLs that use this DLL. + // + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); +#if 0 + bool process_teardown_workaround = false; + if (lpvReserved) { + Init::InitInfo info; + status = Init::Info(info); + if (status) break; + if (!info.isNT) process_teardown_workaround = true; + } + if (process_teardown_workaround) + break; +#endif + // return value is ignored, so we set status for debugging purposes + status = Client::Cleanup(); + status = Init::Cleanup(); + ReleaseMutex( hCCAPIv2Mutex ); + CloseHandle( hCCAPIv2Mutex ); + //-- Copied from previous implementation. + + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata); + TlsFree(dwTlsIndex); // Release the TLS index. + break; + + default: break; + } + + UNREFERENCED_PARAMETER(hinstDLL); // no whining! + UNREFERENCED_PARAMETER(lpvReserved); + return status ? FALSE : TRUE; +} + + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/krb5-1-7/src/ccapi/lib/win/dllmain.h b/krb5-1-7/src/ccapi/lib/win/dllmain.h new file mode 100644 index 000000000..abf6afd4a --- /dev/null +++ b/krb5-1-7/src/ccapi/lib/win/dllmain.h @@ -0,0 +1,42 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 _dll_h +#define _dll_h + +#include "windows.h" + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +DWORD GetTlsIndex(); + +#ifdef __cplusplus +} +#endif + +#endif _dll_h \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/server/Makefile.in b/krb5-1-7/src/ccapi/server/Makefile.in new file mode 100644 index 000000000..d7d9a4d1e --- /dev/null +++ b/krb5-1-7/src/ccapi/server/Makefile.in @@ -0,0 +1,62 @@ +thisconfigdir=../.. +myfulldir=ccapi/server +mydir=ccapi/server +BUILDTOP=$(REL)..$(S).. +SUBDIRS=unix + +LOCALINCLUDES= -I$(srcdir)/../common + +STLIBOBJS= \ + ccs_array.o \ + ccs_cache_collection.o \ + ccs_callback.o \ + ccs_ccache.o \ + ccs_ccache_iterator.o \ + ccs_client.o \ + ccs_credentials.o \ + ccs_credentials_iterator.o \ + ccs_list.o \ + ccs_list_internal.o \ + ccs_lock.o \ + ccs_lock_state.o \ + ccs_pipe.o \ + ccs_server.o + +OBJS= \ + $(OUTPRE)ccs_array.$(OBJEXT) \ + $(OUTPRE)ccs_cache_collection.$(OBJEXT) \ + $(OUTPRE)ccs_callback.$(OBJEXT) \ + $(OUTPRE)ccs_ccache.$(OBJEXT) \ + $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_client.$(OBJEXT) \ + $(OUTPRE)ccs_credentials.$(OBJEXT) \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_list.$(OBJEXT) \ + $(OUTPRE)ccs_list_internal.$(OBJEXT) \ + $(OUTPRE)ccs_lock.$(OBJEXT) \ + $(OUTPRE)ccs_lock_state.$(OBJEXT) \ + $(OUTPRE)ccs_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_server.$(OBJEXT) + +SRCS= \ + ccs_array.c \ + ccs_cache_collection.c \ + ccs_callback.c \ + ccs_ccache.c \ + ccs_ccache_iterator.c \ + ccs_client.c \ + ccs_credentials.c \ + ccs_credentials_iterator.c \ + ccs_list.c \ + ccs_list_internal.c \ + ccs_lock.c \ + ccs_lock_state.c \ + ccs_pipe.c \ + ccs_server.c + +all-unix:: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + +# +++ Dependency line eater +++ diff --git a/krb5-1-7/src/ccapi/server/ccs_array.c b/krb5-1-7/src/ccapi/server/ccs_array.c new file mode 100644 index 000000000..d5dd4adb2 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_array.c @@ -0,0 +1,310 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "cci_array_internal.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_client_object_release (cci_array_object_t io_client) +{ + return cci_check_error (ccs_client_release ((ccs_client_t) io_client)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_new (ccs_client_array_t *out_array) +{ + return cci_array_new (out_array, ccs_client_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_release (ccs_client_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_client_array_count (ccs_client_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_client_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_insert (ccs_client_array_t io_array, + ccs_client_t in_client, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_client, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_remove (ccs_client_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_object_release (cci_array_object_t io_lock) +{ + return cci_check_error (ccs_lock_release ((ccs_lock_t) io_lock)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array) +{ + return cci_array_new (out_array, ccs_lock_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_lock_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array, + ccs_lock_t in_lock, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_lock, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ +cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position) +{ + return cci_array_move (io_array, in_position, in_new_position, out_real_new_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_callback_object_release (cci_array_object_t io_callback) +{ + return cci_check_error (ccs_callback_release ((ccs_callback_t) io_callback)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array) +{ + return cci_array_new (out_array, ccs_callback_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_callback_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array) +{ + /* Ref arrays do not own their contents; pass NULL for release function */ + return cci_array_new (out_array, NULL); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_callback_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array) +{ + /* Ref arrays do not own their contents; pass NULL for release function */ + return cci_array_new (out_array, NULL); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_generic_list_iterator_t) cci_array_object_at_index (io_array, + in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array, + ccs_generic_list_iterator_t in_iterator, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, + (cci_array_object_t) in_iterator, + in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_array.h b/krb5-1-7/src/ccapi/server/ccs_array.h new file mode 100644 index 000000000..93dc9d8c2 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_array.h @@ -0,0 +1,133 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 CCS_ARRAY_H +#define CCS_ARRAY_H + +#include "ccs_types.h" + +cc_int32 ccs_client_array_new (ccs_client_array_t *out_array); + +cc_int32 ccs_client_array_release (ccs_client_array_t io_array); + +cc_uint64 ccs_client_array_count (ccs_client_array_t in_array); + +ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_client_array_insert (ccs_client_array_t io_array, + ccs_client_t in_client, + cc_uint64 in_position); + +cc_int32 ccs_client_array_remove (ccs_client_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array); + +cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array); + +cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array); + +ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array, + ccs_lock_t in_lock, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array); + +cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array); + +cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array); + +ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position); + +cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array); + +cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array); + +cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array); + +ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position); + +cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array); + +cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array); + +cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array); + +ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array, + ccs_generic_list_iterator_t in_iterator, + cc_uint64 in_position); + +cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array, + cc_uint64 in_position); + +#endif /* CCS_ARRAY_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_cache_collection.c b/krb5-1-7/src/ccapi/server/ccs_cache_collection.c new file mode 100644 index 000000000..3790a10aa --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_cache_collection.c @@ -0,0 +1,1110 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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-platform.h" /* pull in asprintf decl/defn */ +#include "ccs_common.h" +#include "ccs_os_notify.h" + +struct ccs_cache_collection_d { + cc_time_t last_changed_time; + cc_uint64 next_unique_name; + cci_identifier_t identifier; + ccs_lock_state_t lock_state; + ccs_ccache_list_t ccaches; + ccs_callback_array_t change_callbacks; +}; + +struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection) +{ + cc_int32 err = ccNoError; + ccs_cache_collection_t cache_collection = NULL; + + if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cache_collection = malloc (sizeof (*cache_collection)); + if (cache_collection) { + *cache_collection = ccs_cache_collection_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&cache_collection->identifier); + } + + if (!err) { + err = ccs_lock_state_new (&cache_collection->lock_state, + ccErrInvalidContext, + ccErrContextLocked, + ccErrContextUnlocked); + } + + if (!err) { + err = ccs_ccache_list_new (&cache_collection->ccaches); + } + + if (!err) { + err = ccs_callback_array_new (&cache_collection->change_callbacks); + } + + if (!err) { + err = ccs_cache_collection_changed (cache_collection); + } + + if (!err) { + *out_cache_collection = cache_collection; + cache_collection = NULL; + } + + ccs_cache_collection_release (cache_collection); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + + if (!err && io_cache_collection) { + cci_identifier_release (io_cache_collection->identifier); + ccs_lock_state_release (io_cache_collection->lock_state); + ccs_ccache_list_release (io_cache_collection->ccaches); + ccs_callback_array_release (io_cache_collection->change_callbacks); + free (io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_cache_collection->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_time_t now = time (NULL); + + if (io_cache_collection->last_changed_time < now) { + io_cache_collection->last_changed_time = now; + } else { + io_cache_collection->last_changed_time++; + } + } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + err = k5_ipc_stream_write_time (reply_data, io_cache_collection->last_changed_time); + } + + if (!err) { + /* Loop over callbacks sending messages to them */ + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (io_cache_collection->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (io_cache_collection->change_callbacks, i); + + err = ccs_callback_reply_to_client (callback, reply_data); + + if (!err) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (io_cache_collection->change_callbacks, i); + break; + } + } + } + + if (!err) { + err = ccs_os_notify_cache_collection_changed (io_cache_collection); + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_invalidate_change_callback (ccs_callback_owner_t io_cache_collection, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Remove callback */ + ccs_cache_collection_t cache_collection = (ccs_cache_collection_t) io_cache_collection; + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (cache_collection->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (cache_collection->change_callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (cache_collection->change_callbacks, i); + break; + } + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t in_cache_collection, + const char *in_name, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + ccs_ccache_list_iterator_t iterator = NULL; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + } + + while (!err) { + ccs_ccache_t ccache = NULL; + + err = ccs_ccache_list_iterator_next (iterator, &ccache); + + if (!err) { + cc_uint32 equal = 0; + + err = ccs_ccache_compare_name (ccache, in_name, &equal); + + if (!err && equal) { + *out_ccache = ccache; + break; + } + } + } + if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; } + + if (iterator) { ccs_ccache_list_iterator_release (iterator); } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_find (in_cache_collection->ccaches, + in_identifier, out_ccache); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_source_identifier, + ccs_ccache_t io_destination_ccache) +{ + cc_int32 err = ccNoError; + ccs_ccache_t source_ccache = NULL; + + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_find_ccache (io_cache_collection, + in_source_identifier, + &source_ccache); + } + + if (!err) { + err = ccs_ccache_swap_contents (source_ccache, + io_destination_ccache, + io_cache_collection); + } + + if (!err) { + err = ccs_cache_collection_destroy_ccache (io_cache_collection, + in_source_identifier); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_find_ccache (io_cache_collection, + in_identifier, + &ccache); + } + + if (!err) { + /* Notify before deletion because after deletion the ccache + * will no longer exist (and won't know about its clients) */ + err = ccs_ccache_changed (ccache, io_cache_collection); + } + + if (!err) { + err = ccs_ccache_list_remove (io_cache_collection->ccaches, + in_identifier); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_iterator_t *out_ccache_iterator) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches, + in_identifier, + out_ccache_iterator); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache, + ccs_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + ccs_ccache_list_iterator_t iterator = NULL; + + if (!in_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + } + + while (!err) { + ccs_ccache_t ccache = NULL; + + err = ccs_ccache_list_iterator_next (iterator, &ccache); + + if (!err) { + cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache, + in_identifier, + out_credentials_iterator); + if (!terr) { + *out_ccache = ccache; + break; + } + } + } + if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); } + + if (iterator) { ccs_ccache_list_iterator_release (iterator); } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t io_cache_collection, + char **out_name) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + char *name = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + while (!err) { + int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++); + if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + ccs_ccache_t ccache = NULL; /* temporary to hold ccache pointer */ + err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, &ccache); + } + + if (err == ccErrCCacheNotFound) { + err = ccNoError; + break; /* found a unique one */ + } + } + } else { + name = strdup (k_cci_context_initial_ccache_name); + if (!name) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + *out_name = name; + name = NULL; + } + + free (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t in_cache_collection, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_count (in_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + /* First ccache is the default */ + ccs_ccache_list_iterator_t iterator = NULL; + + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + + if (!err) { + err = ccs_ccache_list_iterator_next (iterator, out_ccache); + } + + ccs_ccache_list_iterator_release (iterator); + + } else { + err = cci_check_error (ccErrCCacheNotFound); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_ccache_t old_default = NULL; + ccs_ccache_t new_default = NULL; + cc_uint32 equal = 0; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &old_default); + } + + if (!err) { + err = ccs_ccache_compare_identifier (old_default, in_identifier, &equal); + } + + + if (!err && !equal) { + err = ccs_ccache_list_push_front (io_cache_collection->ccaches, + in_identifier); + + if (!err) { + err = ccs_ccache_notify_default_state_changed (old_default, + io_cache_collection, + 0 /* no longer default */); + } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &new_default); + } + + if (!err) { + err = ccs_ccache_notify_default_state_changed (new_default, + io_cache_collection, + 1 /* now default */); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#pragma mark -- IPC Messages -- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (io_cache_collection->identifier, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_wait_for_change (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data, + cc_uint32 *out_will_block) +{ + cc_int32 err = ccNoError; + cc_time_t last_wait_for_change_time = 0; + cc_uint32 will_block = 0; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_time (in_request_data, &last_wait_for_change_time); + } + + if (!err) { + if (last_wait_for_change_time < io_cache_collection->last_changed_time) { + err = k5_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); + + } else { + ccs_callback_t callback = NULL; + + err = ccs_callback_new (&callback, + ccErrInvalidContext, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) io_cache_collection, + ccs_cache_collection_invalidate_change_callback); + + if (!err) { + err = ccs_callback_array_insert (io_cache_collection->change_callbacks, callback, + ccs_callback_array_count (io_cache_collection->change_callbacks)); + if (!err) { callback = NULL; /* take ownership */ } + + will_block = 1; + } + + ccs_callback_release (callback); + } + } + + if (!err) { + *out_will_block = will_block; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache); + + if (!err) { + err = ccs_ccache_write_name (ccache, io_reply_data); + } + } else { + err = k5_ipc_stream_write_string (io_reply_data, + k_cci_context_initial_ccache_name); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + char *name = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &name); + } + + if (!err) { + err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + k5_ipc_stream_free_string (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + char *name = NULL; + cc_uint32 cred_vers; + char *principal = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &name); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, + &ccache); + + if (!terr) { + err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); + + } else { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + k5_ipc_stream_free_string (name); + k5_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers; + char *principal = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &ccache); + + if (!err) { + err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); + + } else if (err == ccErrCCacheNotFound) { + char *name = NULL; + + err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, + &name); + + if (!err) { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + + free (name); + } + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + k5_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers; + char *principal = NULL; + char *name = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, + &name); + } + + if (!err) { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + free (name); + k5_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection, + ccs_pipe_t in_client_pipe, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_iterator_t ccache_iterator = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches, + in_client_pipe, + &ccache_iterator); + } + + if (!err) { + err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_lock (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 lock_type; + cc_uint32 block; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &lock_type); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &block); + } + + if (!err) { + err = ccs_lock_state_add (io_cache_collection->lock_state, + in_client_pipe, in_reply_pipe, + lock_type, block, out_will_block); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t in_client_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_state_remove (io_cache_collection->lock_state, + in_client_pipe); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_context_unused_release_msg_id) { + /* Old release message. Do nothing. */ + + } else if (in_request_name == cci_context_sync_msg_id) { + err = ccs_cache_collection_sync (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_get_change_time_msg_id) { + err = ccs_cache_collection_get_change_time (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_wait_for_change_msg_id) { + err = ccs_cache_collection_wait_for_change (in_client_pipe, in_reply_pipe, + io_cache_collection, + in_request_data, reply_data, + &will_block); + + } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) { + err = ccs_cache_collection_get_default_ccache_name (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_open_ccache_msg_id) { + err = ccs_cache_collection_open_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_open_default_ccache_msg_id) { + err = ccs_cache_collection_open_default_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_ccache_msg_id) { + err = ccs_cache_collection_create_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_default_ccache_msg_id) { + err = ccs_cache_collection_create_default_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_new_ccache_msg_id) { + err = ccs_cache_collection_create_new_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) { + err = ccs_cache_collection_new_ccache_iterator (io_cache_collection, + in_client_pipe, + in_request_data, + reply_data); + + } else if (in_request_name == cci_context_lock_msg_id) { + err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe, + io_cache_collection, + in_request_data, + &will_block, reply_data); + + } else if (in_request_name == cci_context_unlock_msg_id) { + err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection, + in_request_data, reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_will_block = will_block; + if (!will_block) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } else { + *out_reply_data = NULL; + } + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_cache_collection.h b/krb5-1-7/src/ccapi/server/ccs_cache_collection.h new file mode 100644 index 000000000..f0507967b --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_cache_collection.h @@ -0,0 +1,73 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CACHE_COLLECTION_H +#define CCS_CACHE_COLLECTION_H + +#include "ccs_types.h" + +cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection); + +cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_source_identifier, + ccs_ccache_t io_destination_ccache); + +cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_iterator_t *out_ccache_iterator); + +cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache, + ccs_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CACHE_COLLECTION_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_callback.c b/krb5-1-7/src/ccapi/server/ccs_callback.c new file mode 100644 index 000000000..94e9d9b4b --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_callback.c @@ -0,0 +1,239 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" + +struct ccs_callback_d { + cc_int32 pending; + cc_int32 invalid_object_err; + ccs_pipe_t client_pipe; + ccs_pipe_t reply_pipe; + ccs_callback_owner_t owner; /* pointer to owner */ + ccs_callback_owner_invalidate_t owner_invalidate; +}; + +struct ccs_callback_d ccs_callback_initializer = { 1, 1, CCS_PIPE_NULL, CCS_PIPE_NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_new (ccs_callback_t *out_callback, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_callback_owner_t in_owner, + ccs_callback_owner_invalidate_t in_owner_invalidate_function) +{ + cc_int32 err = ccNoError; + ccs_callback_t callback = NULL; + ccs_client_t client = NULL; + + if (!out_callback ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_owner ) { err = cci_check_error (ccErrBadParam); } + if (!in_owner_invalidate_function ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + callback = malloc (sizeof (*callback)); + if (callback) { + *callback = ccs_callback_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + err = ccs_pipe_copy (&callback->client_pipe, in_client_pipe); + } + + if (!err) { + err = ccs_pipe_copy (&callback->reply_pipe, in_reply_pipe); + } + + if (!err) { + callback->client_pipe = in_client_pipe; + callback->reply_pipe = in_reply_pipe; + callback->invalid_object_err = in_invalid_object_err; + callback->owner = in_owner; + callback->owner_invalidate = in_owner_invalidate_function; + + err = ccs_client_add_callback (client, callback); + } + + if (!err) { + *out_callback = callback; + callback = NULL; + } + + ccs_callback_release (callback); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_release (ccs_callback_t io_callback) +{ + cc_int32 err = ccNoError; + + if (!err && io_callback) { + ccs_client_t client = NULL; + + if (io_callback->pending) { + err = ccs_server_send_reply (io_callback->reply_pipe, + io_callback->invalid_object_err, NULL); + + io_callback->pending = 0; + } + + if (!err) { + err = ccs_server_client_for_pipe (io_callback->client_pipe, &client); + } + + if (!err && client) { + /* if client object still has a reference to us, remove it */ + err = ccs_client_remove_callback (client, io_callback); + } + + if (!err) { + ccs_pipe_release (io_callback->client_pipe); + ccs_pipe_release (io_callback->reply_pipe); + free (io_callback); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback) +{ + cc_int32 err = ccNoError; + + if (!io_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + io_callback->pending = 0; /* client is dead, don't try to talk to it */ + if (io_callback->owner_invalidate) { + err = io_callback->owner_invalidate (io_callback->owner, io_callback); + } else { + cci_debug_printf ("WARNING %s() unable to notify callback owner!", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + + if (!io_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_callback->pending) { + cci_debug_printf ("%s: callback %p replying to client.", __FUNCTION__, io_callback); + + err = ccs_server_send_reply (io_callback->reply_pipe, err, in_stream); + + if (err) { + cci_debug_printf ("WARNING %s() called on a lock belonging to a dead client!", + __FUNCTION__); + } + + io_callback->pending = 0; + } else { + cci_debug_printf ("WARNING %s() called on non-pending callback!", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback, + cc_uint32 *out_pending) +{ + cc_int32 err = ccNoError; + + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + if (!out_pending) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_pending = in_callback->pending; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_is_for_client_pipe ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_pipe_compare (in_callback->client_pipe, in_client_pipe, + out_is_for_client_pipe); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t *out_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_client_pipe = in_callback->client_pipe; + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_callback.h b/krb5-1-7/src/ccapi/server/ccs_callback.h new file mode 100644 index 000000000..26526984e --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_callback.h @@ -0,0 +1,62 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CALLBACK_H +#define CCS_CALLBACK_H + +#include "ccs_types.h" + +struct ccs_callback_owner_d; +typedef struct ccs_callback_owner_d *ccs_callback_owner_t; + +typedef cc_int32 (*ccs_callback_owner_invalidate_t) (ccs_callback_owner_t, ccs_callback_t); + + +cc_int32 ccs_callback_new (ccs_callback_t *out_callback, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_callback_owner_t in_owner, + ccs_callback_owner_invalidate_t in_owner_invalidate_function); + +cc_int32 ccs_callback_release (ccs_callback_t io_callback); + +cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback); + +cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback, + k5_ipc_stream in_stream); + +cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback, + cc_uint32 *out_pending); + +cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe); + +cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t *out_client_pipe); + +#endif /* CCS_CALLBACK_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_ccache.c b/krb5-1-7/src/ccapi/server/ccs_ccache.c new file mode 100644 index 000000000..88cf1e0d9 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_ccache.c @@ -0,0 +1,1238 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "ccs_os_notify.h" + +struct ccs_ccache_d { + cci_identifier_t identifier; + ccs_lock_state_t lock_state; + cc_uint32 creds_version; + char *name; + char *v4_principal; + char *v5_principal; + cc_time_t last_default_time; + cc_time_t last_changed_time; + cc_uint32 kdc_time_offset_v4_valid; + cc_time_t kdc_time_offset_v4; + cc_uint32 kdc_time_offset_v5_valid; + cc_time_t kdc_time_offset_v5; + ccs_credentials_list_t credentials; + ccs_callback_array_t change_callbacks; +}; + +struct ccs_ccache_d ccs_ccache_initializer = { NULL, NULL, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache, + cc_uint32 in_creds_version, + const char *in_name, + const char *in_principal, + ccs_ccache_list_t io_ccache_list) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache = malloc (sizeof (*ccache)); + if (ccache) { + *ccache = ccs_ccache_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&ccache->identifier); + } + + if (!err) { + err = ccs_lock_state_new (&ccache->lock_state, + ccErrInvalidCCache, + ccErrCCacheLocked, + ccErrCCacheUnlocked); + } + + if (!err) { + ccache->name = strdup (in_name); + if (!ccache->name) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + ccache->creds_version = in_creds_version; + + if (ccache->creds_version == cc_credentials_v4) { + ccache->v4_principal = strdup (in_principal); + if (!ccache->v4_principal) { err = cci_check_error (ccErrNoMem); } + + } else if (ccache->creds_version == cc_credentials_v5) { + ccache->v5_principal = strdup (in_principal); + if (!ccache->v5_principal) { err = cci_check_error (ccErrNoMem); } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_credentials_list_new (&ccache->credentials); + } + + if (!err) { + err = ccs_callback_array_new (&ccache->change_callbacks); + } + + if (!err) { + cc_uint64 now = time (NULL); + cc_uint64 count = 0; + + err = ccs_ccache_list_count (io_ccache_list, &count); + + if (!err) { + /* first cache is default */ + ccache->last_default_time = (count == 0) ? now : 0; + cci_debug_printf ("%s ccache->last_default_time is %d.", + __FUNCTION__, ccache->last_default_time); + ccache->last_changed_time = now; + } + } + + if (!err) { + /* Add self to the list of ccaches */ + err = ccs_ccache_list_add (io_ccache_list, ccache); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + ccs_ccache_release (ccache); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_creds_version, + const char *in_principal) +{ + cc_int32 err = ccNoError; + char *v4_principal = NULL; + char *v5_principal = NULL; + ccs_credentials_list_t credentials = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_principal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + io_ccache->creds_version = in_creds_version; + + if (io_ccache->creds_version == cc_credentials_v4) { + v4_principal = strdup (in_principal); + if (!v4_principal) { err = cci_check_error (ccErrNoMem); } + + } else if (io_ccache->creds_version == cc_credentials_v5) { + v5_principal = strdup (in_principal); + if (!v5_principal) { err = cci_check_error (ccErrNoMem); } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_credentials_list_new (&credentials); + } + + if (!err) { + io_ccache->kdc_time_offset_v4 = 0; + io_ccache->kdc_time_offset_v4_valid = 0; + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + if (io_ccache->v4_principal) { free (io_ccache->v4_principal); } + io_ccache->v4_principal = v4_principal; + v4_principal = NULL; /* take ownership */ + + if (io_ccache->v5_principal) { free (io_ccache->v5_principal); } + io_ccache->v5_principal = v5_principal; + v5_principal = NULL; /* take ownership */ + + ccs_credentials_list_release (io_ccache->credentials); + io_ccache->credentials = credentials; + credentials = NULL; /* take ownership */ + + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + free (v4_principal); + free (v5_principal); + ccs_credentials_list_release (credentials); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, + ccs_ccache_t io_destination_ccache, + ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + + if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + struct ccs_ccache_d temp_ccache = *io_destination_ccache; + + /* swap everything */ + *io_destination_ccache = *io_source_ccache; + *io_source_ccache = temp_ccache; + + /* swap back the name and identifier */ + io_source_ccache->identifier = io_destination_ccache->identifier; + io_destination_ccache->identifier = temp_ccache.identifier; + + io_source_ccache->name = io_destination_ccache->name; + io_destination_ccache->name = temp_ccache.name; + } + + if (!err) { + err = ccs_ccache_changed (io_source_ccache, io_cache_collection); + } + + if (!err) { + err = ccs_ccache_changed (io_destination_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + + if (!err && io_ccache) { + cci_identifier_release (io_ccache->identifier); + ccs_lock_state_release (io_ccache->lock_state); + free (io_ccache->name); + free (io_ccache->v4_principal); + free (io_ccache->v5_principal); + ccs_credentials_list_release (io_ccache->credentials); + ccs_callback_array_release (io_ccache->change_callbacks); + free (io_ccache); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_ccache->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache, + const char *in_name, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_equal = (strcmp (in_ccache->name, in_name) == 0); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_time_t now = time (NULL); + + if (io_ccache->last_changed_time < now) { + io_ccache->last_changed_time = now; + } else { + io_ccache->last_changed_time++; + } + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + err = k5_ipc_stream_write_time (reply_data, io_ccache->last_changed_time); + } + + if (!err) { + /* Loop over callbacks sending messages to them */ + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (io_ccache->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (io_ccache->change_callbacks, i); + + err = ccs_callback_reply_to_client (callback, reply_data); + + if (!err) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (io_ccache->change_callbacks, i); + break; + } + } + } + + if (!err) { + err = ccs_os_notify_ccache_changed (io_cache_collection, + io_ccache->name); + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_invalidate_change_callback (ccs_callback_owner_t io_ccache, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Remove callback */ + ccs_ccache_t ccache = (ccs_ccache_t) io_ccache; + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (ccache->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (ccache->change_callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (ccache->change_callbacks, i); + break; + } + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_new_default_state) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_new_default_state) { + cc_time_t now = time (NULL); + + if (io_ccache->last_default_time < now) { + io_ccache->last_default_time = now; + } else { + io_ccache->last_default_time++; + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + ccs_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_find_iterator (in_ccache->credentials, + in_identifier, + out_credentials_iterator); + } + + // Don't report ccErrInvalidCredentials to the log file. Non-fatal. + return (err == ccErrInvalidCredentials) ? err : cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_ccache->identifier, io_stream); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, in_ccache->name); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#pragma mark -- IPC Messages -- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_destroy (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_destroy_ccache (io_cache_collection, + io_ccache->identifier); + } + + if (!err) { + /* ccache has been destroyed so just mark the cache collection */ + err = ccs_cache_collection_changed (io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_default (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_set_default_ccache (io_cache_collection, + io_ccache->identifier); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_credentials_version (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_write_uint32 (io_reply_data, io_ccache->creds_version); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_name (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_write_string (io_reply_data, io_ccache->name); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_principal (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 version = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &version); + } + + if (!err && version == cc_credentials_v4_v5) { + err = cci_check_error (ccErrBadCredentialsVersion); + } + + if (!err) { + if (version == cc_credentials_v4) { + err = k5_ipc_stream_write_string (io_reply_data, io_ccache->v4_principal); + + } else if (version == cc_credentials_v5) { + err = k5_ipc_stream_write_string (io_reply_data, io_ccache->v5_principal); + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_principal (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 version = 0; + char *principal = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &version); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + /* reset KDC time offsets because they are per-KDC */ + if (version == cc_credentials_v4) { + io_ccache->kdc_time_offset_v4 = 0; + io_ccache->kdc_time_offset_v4_valid = 0; + + if (io_ccache->v4_principal) { free (io_ccache->v4_principal); } + io_ccache->v4_principal = principal; + principal = NULL; /* take ownership */ + + + } else if (version == cc_credentials_v5) { + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + if (io_ccache->v5_principal) { free (io_ccache->v5_principal); } + io_ccache->v5_principal = principal; + principal = NULL; /* take ownership */ + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + io_ccache->creds_version |= version; + + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + k5_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_store_credentials (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_new (&credentials, in_request_data, + io_ccache->creds_version, + io_ccache->credentials); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_remove_credentials (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cci_identifier_t credentials_identifier = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_read (&credentials_identifier, in_request_data); + } + + if (!err) { + err = ccs_credentials_list_remove (io_ccache->credentials, credentials_identifier); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + cci_identifier_release (credentials_identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_new_credentials_iterator (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + ccs_pipe_t in_client_pipe, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_iterator_t credentials_iterator = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_new_iterator (io_ccache->credentials, + in_client_pipe, + &credentials_iterator); + } + + if (!err) { + err = ccs_credentials_list_iterator_write (credentials_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_move (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cci_identifier_t source_identifier = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Note: message is sent as the destination ccache to avoid */ + /* extra work on the server when deleting it the source ccache. */ + err = cci_identifier_read (&source_identifier, in_request_data); + } + + if (!err) { + err = ccs_ccache_collection_move_ccache (io_cache_collection, + source_identifier, + io_ccache); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + cci_identifier_release (source_identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_lock (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 lock_type; + cc_uint32 block; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &lock_type); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &block); + } + + if (!err) { + err = ccs_lock_state_add (io_ccache->lock_state, + in_client_pipe, in_reply_pipe, + lock_type, block, out_will_block); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_unlock (ccs_pipe_t in_client_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_state_remove (io_ccache->lock_state, in_client_pipe); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_last_default_time (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err && io_ccache->last_default_time == 0) { + err = cci_check_error (ccErrNeverDefault); + } + + if (!err) { + err = k5_ipc_stream_write_time (io_reply_data, io_ccache->last_default_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_change_time (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_write_time (io_reply_data, io_ccache->last_changed_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_wait_for_change (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data, + cc_uint32 *out_will_block) +{ + cc_int32 err = ccNoError; + cc_time_t last_wait_for_change_time = 0; + cc_uint32 will_block = 0; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_time (in_request_data, &last_wait_for_change_time); + } + + if (!err) { + if (last_wait_for_change_time < io_ccache->last_changed_time) { + cci_debug_printf ("%s returning immediately", __FUNCTION__); + err = k5_ipc_stream_write_time (io_reply_data, io_ccache->last_changed_time); + + } else { + ccs_callback_t callback = NULL; + + err = ccs_callback_new (&callback, + ccErrInvalidCCache, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) io_ccache, + ccs_ccache_invalidate_change_callback); + + if (!err) { + err = ccs_callback_array_insert (io_ccache->change_callbacks, callback, + ccs_callback_array_count (io_ccache->change_callbacks)); + if (!err) { callback = NULL; /* take ownership */ } + + cci_debug_printf ("%s blocking", __FUNCTION__); + will_block = 1; + } + + ccs_callback_release (callback); + } + } + + if (!err) { + *out_will_block = will_block; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v4) { + if (io_ccache->kdc_time_offset_v4_valid) { + err = k5_ipc_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v4); + } else { + err = cci_check_error (ccErrTimeOffsetNotSet); + } + + } else if (cred_vers == cc_credentials_v5) { + if (io_ccache->kdc_time_offset_v5_valid) { + err = k5_ipc_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v5); + } else { + err = cci_check_error (ccErrTimeOffsetNotSet); + } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v4) { + err = k5_ipc_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v4); + + if (!err) { + io_ccache->kdc_time_offset_v4_valid = 1; + } + } else if (cred_vers == cc_credentials_v5) { + err = k5_ipc_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v5); + + if (!err) { + io_ccache->kdc_time_offset_v5_valid = 1; + } + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_clear_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v4) { + io_ccache->kdc_time_offset_v4 = 0; + io_ccache->kdc_time_offset_v4_valid = 0; + + } else if (cred_vers == cc_credentials_v5) { + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_ccache_destroy_msg_id) { + err = ccs_ccache_destroy (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_default_msg_id) { + err = ccs_ccache_set_default (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_credentials_version_msg_id) { + err = ccs_ccache_get_credentials_version (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_name_msg_id) { + err = ccs_ccache_get_name (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_principal_msg_id) { + err = ccs_ccache_get_principal (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_principal_msg_id) { + err = ccs_ccache_set_principal (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_store_credentials_msg_id) { + err = ccs_ccache_store_credentials (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_remove_credentials_msg_id) { + err = ccs_ccache_remove_credentials (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_new_credentials_iterator_msg_id) { + err = ccs_ccache_new_credentials_iterator (io_ccache, + io_cache_collection, + in_client_pipe, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_move_msg_id) { + err = ccs_ccache_move (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_lock_msg_id) { + err = ccs_ccache_lock (in_client_pipe, in_reply_pipe, + io_ccache, io_cache_collection, + in_request_data, + &will_block, reply_data); + + } else if (in_request_name == cci_ccache_unlock_msg_id) { + err = ccs_ccache_unlock (in_client_pipe, + io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_last_default_time_msg_id) { + err = ccs_ccache_get_last_default_time (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_change_time_msg_id) { + err = ccs_ccache_get_change_time (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_wait_for_change_msg_id) { + err = ccs_ccache_wait_for_change (in_client_pipe, in_reply_pipe, + io_ccache, io_cache_collection, + in_request_data, reply_data, + &will_block); + + } else if (in_request_name == cci_ccache_get_kdc_time_offset_msg_id) { + err = ccs_ccache_get_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_kdc_time_offset_msg_id) { + err = ccs_ccache_set_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_clear_kdc_time_offset_msg_id) { + err = ccs_ccache_clear_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_will_block = will_block; + if (!will_block) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } else { + *out_reply_data = NULL; + } + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/server/ccs_ccache.h b/krb5-1-7/src/ccapi/server/ccs_ccache.h new file mode 100644 index 000000000..21c9f410f --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_ccache.h @@ -0,0 +1,83 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CCACHE_H +#define CCS_CCACHE_H + +#include "ccs_types.h" + +cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache, + cc_uint32 in_cred_vers, + const char *in_name, + const char *in_principal, + ccs_ccache_list_t io_ccache_list); + +cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_cred_vers, + const char *in_principal); + +cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, + ccs_ccache_t io_destination_ccache, + ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache); + +cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache, + const char *in_name, + cc_uint32 *out_equal); + +cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_new_default_state); + +cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + ccs_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream); + +cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream); + +cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CCACHE_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.c b/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.c new file mode 100644 index 000000000..0e0505644 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.c @@ -0,0 +1,158 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_release (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_release (io_ccache_iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_next (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_next (io_ccache_iterator, &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_clone (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_iterator_t ccache_iterator = NULL; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_clone (io_ccache_iterator, + &ccache_iterator); + } + + if (!err) { + err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!in_request_data) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_ccache_iterator_release_msg_id) { + err = ccs_ccache_iterator_release (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_iterator_next_msg_id) { + err = ccs_ccache_iterator_next (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_iterator_clone_msg_id) { + err = ccs_ccache_iterator_clone (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.h b/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.h new file mode 100644 index 000000000..642ebcc5b --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_ccache_iterator.h @@ -0,0 +1,38 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CCACHE_ITERATOR_H +#define CCS_CCACHE_ITERATOR_H + +#include "ccs_types.h" + + cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CCACHE_ITERATOR_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_client.c b/krb5-1-7/src/ccapi/server/ccs_client.c new file mode 100644 index 000000000..31ed14ff4 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_client.c @@ -0,0 +1,237 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" + +struct ccs_client_d { + ccs_pipe_t client_pipe; + + /* The following arrays do not own their contents */ + ccs_callbackref_array_t callbacks; + ccs_iteratorref_array_t iterators; +}; + +struct ccs_client_d ccs_client_initializer = { CCS_PIPE_NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_new (ccs_client_t *out_client, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!out_client ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + client = malloc (sizeof (*client)); + if (client) { + *client = ccs_client_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_callbackref_array_new (&client->callbacks); + } + + if (!err) { + err = ccs_iteratorref_array_new (&client->iterators); + } + + if (!err) { + err = ccs_pipe_copy (&client->client_pipe, in_client_pipe); + } + + if (!err) { + *out_client = client; + client = NULL; + } + + ccs_client_release (client); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_release (ccs_client_t io_client) +{ + cc_int32 err = ccNoError; + + if (!err && io_client) { + cc_uint64 i; + cc_uint64 callback_count = ccs_callbackref_array_count (io_client->callbacks); + cc_uint64 iterator_count = ccs_iteratorref_array_count (io_client->iterators); + + for (i = 0; !err && i < callback_count; i++) { + ccs_callback_t callback = ccs_callbackref_array_object_at_index (io_client->callbacks, i); + + cci_debug_printf ("%s: Invalidating callback reference %p.", + __FUNCTION__, callback); + ccs_callback_invalidate (callback); + } + + for (i = 0; !err && i < iterator_count; i++) { + ccs_generic_list_iterator_t iterator = ccs_iteratorref_array_object_at_index (io_client->iterators, i); + + cci_debug_printf ("%s: Invalidating iterator reference %p.", + __FUNCTION__, iterator); + ccs_generic_list_iterator_invalidate (iterator); + } + + ccs_callbackref_array_release (io_client->callbacks); + ccs_iteratorref_array_release (io_client->iterators); + ccs_pipe_release (io_client->client_pipe); + free (io_client); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_add_callback (ccs_client_t io_client, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callbackref_array_insert (io_client->callbacks, in_callback, + ccs_callbackref_array_count (io_client->callbacks)); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_remove_callback (ccs_client_t io_client, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + cc_uint32 found_callback = 0; + + if (!io_client) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = ccs_callbackref_array_count (io_client->callbacks); + + for (i = 0; !err && i < lock_count; i++) { + ccs_callback_t callback = ccs_callbackref_array_object_at_index (io_client->callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + found_callback = 1; + err = ccs_callbackref_array_remove (io_client->callbacks, i); + break; + } + } + } + + if (!err && !found_callback) { + cci_debug_printf ("%s: WARNING! callback not found.", __FUNCTION__); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_add_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator) +{ + cc_int32 err = ccNoError; + + if (!io_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_iteratorref_array_insert (io_client->iterators, in_iterator, + ccs_iteratorref_array_count (io_client->iterators)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_remove_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator) +{ + cc_int32 err = ccNoError; + cc_uint32 found_iterator = 0; + + if (!io_client) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = ccs_iteratorref_array_count (io_client->iterators); + + for (i = 0; !err && i < lock_count; i++) { + ccs_generic_list_iterator_t iterator = ccs_iteratorref_array_object_at_index (io_client->iterators, i); + + if (iterator == in_iterator) { + cci_debug_printf ("%s: Removing iterator reference %p.", __FUNCTION__, iterator); + found_iterator = 1; + err = ccs_iteratorref_array_remove (io_client->iterators, i); + break; + } + } + } + + if (!err && !found_iterator) { + cci_debug_printf ("%s: WARNING! iterator not found.", __FUNCTION__); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_uses_pipe (ccs_client_t in_client, + ccs_pipe_t in_pipe, + cc_uint32 *out_uses_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_pipe ) { err = cci_check_error (ccErrBadParam); } + if (!out_uses_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_pipe_compare (in_client->client_pipe, in_pipe, out_uses_pipe); + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_client.h b/krb5-1-7/src/ccapi/server/ccs_client.h new file mode 100644 index 000000000..58c963707 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_client.h @@ -0,0 +1,53 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CLIENT_H +#define CCS_CLIENT_H + +#include "ccs_types.h" + +cc_int32 ccs_client_new (ccs_client_t *out_client, + ccs_pipe_t in_client_pipe); + +cc_int32 ccs_client_release (ccs_client_t io_client); + +cc_int32 ccs_client_add_callback (ccs_client_t io_client, + ccs_callback_t in_lock); + +cc_int32 ccs_client_remove_callback (ccs_client_t io_client, + ccs_callback_t in_lock); + +cc_int32 ccs_client_add_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator); + +cc_int32 ccs_client_remove_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator); + +cc_int32 ccs_client_uses_pipe (ccs_client_t in_client, + ccs_pipe_t in_pipe, + cc_uint32 *out_uses_pipe); + +#endif /* CCS_CLIENT_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_common.h b/krb5-1-7/src/ccapi/server/ccs_common.h new file mode 100644 index 000000000..3710b11a3 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_common.h @@ -0,0 +1,48 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_COMMON_H +#define CCS_COMMON_H + +#include "cci_common.h" + +#include + +#include "ccs_array.h" +#include "ccs_list.h" +#include "ccs_cache_collection.h" +#include "ccs_ccache_iterator.h" +#include "ccs_ccache.h" +#include "ccs_credentials_iterator.h" +#include "ccs_credentials.h" +#include "ccs_lock.h" +#include "ccs_lock_state.h" +#include "ccs_pipe.h" +#include "ccs_client.h" +#include "ccs_callback.h" +#include "ccs_server.h" + +#endif /* CCS_COMMON_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_credentials.c b/krb5-1-7/src/ccapi/server/ccs_credentials.c new file mode 100644 index 000000000..56b5a5799 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_credentials.c @@ -0,0 +1,140 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" + +struct ccs_credentials_d { + cc_credentials_union *cred_union; + cci_identifier_t identifier; +}; + +struct ccs_credentials_d ccs_credentials_initializer = { NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials, + k5_ipc_stream in_stream, + cc_uint32 in_ccache_version, + ccs_credentials_list_t io_credentials_list) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!out_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials = malloc (sizeof (*credentials)); + if (credentials) { + *credentials = ccs_credentials_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_credentials_union_read (&credentials->cred_union, in_stream); + } + + if (!err && !(credentials->cred_union->version & in_ccache_version)) { + /* ccache does not have a principal set for this credentials version */ + err = cci_check_error (ccErrBadCredentialsVersion); + } + + if (!err) { + err = ccs_server_new_identifier (&credentials->identifier); + } + + if (!err) { + err = ccs_credentials_list_add (io_credentials_list, credentials); + } + + if (!err) { + *out_credentials = credentials; + credentials = NULL; + } + + ccs_credentials_release (credentials); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials) +{ + cc_int32 err = ccNoError; + + if (!err && io_credentials) { + cci_credentials_union_release (io_credentials->cred_union); + cci_identifier_release (io_credentials->identifier); + free (io_credentials); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_credentials->identifier, io_stream); + } + + if (!err) { + err = cci_credentials_union_write (in_credentials->cred_union, io_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_credentials->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_credentials.h b/krb5-1-7/src/ccapi/server/ccs_credentials.h new file mode 100644 index 000000000..24b279484 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_credentials.h @@ -0,0 +1,47 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CREDENTIALS_H +#define CCS_CREDENTIALS_H + +#include "ccs_types.h" + + +cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials, + k5_ipc_stream in_stream, + cc_uint32 in_ccache_version, + ccs_credentials_list_t io_credentials_list); + +cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials); + +cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials, + k5_ipc_stream io_stream); + +cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +#endif /* CCS_CREDENTIALS_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.c b/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.c new file mode 100644 index 000000000..38e323c26 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.c @@ -0,0 +1,160 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_release (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_release (io_credentials_iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_next (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_next (io_credentials_iterator, + &credentials); + } + + if (!err) { + err = ccs_credentials_write (credentials, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_clone (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_iterator_t credentials_iterator = NULL; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_clone (io_credentials_iterator, + &credentials_iterator); + } + + if (!err) { + err = ccs_credentials_list_iterator_write (credentials_iterator, + io_reply_data); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!in_request_data) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = k5_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_credentials_iterator_release_msg_id) { + err = ccs_credentials_iterator_release (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else if (in_request_name == cci_credentials_iterator_next_msg_id) { + err = ccs_credentials_iterator_next (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else if (in_request_name == cci_credentials_iterator_clone_msg_id) { + err = ccs_credentials_iterator_clone (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } + + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.h b/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.h new file mode 100644 index 000000000..84ff0ba00 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_credentials_iterator.h @@ -0,0 +1,38 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_CREDENTIALS_ITERATOR_H +#define CCS_CREDENTIALS_ITERATOR_H + +#include "ccs_types.h" + + cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CREDENTIALS_ITERATOR_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_list.c b/krb5-1-7/src/ccapi/server/ccs_list.c new file mode 100644 index 000000000..c5b1eb421 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_list.c @@ -0,0 +1,362 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "ccs_list_internal.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_list_object_release (ccs_list_object_t io_object) +{ + return cci_check_error (ccs_cache_collection_release ((ccs_cache_collection_t) io_object)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_list_object_compare_identifier (ccs_list_object_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_cache_collection_compare_identifier ((ccs_cache_collection_t) in_cache_collection, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidContext, + ccErrInvalidContext, + ccs_cache_collection_list_object_compare_identifier, + ccs_cache_collection_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list, + cci_identifier_t in_identifier, + ccs_cache_collection_t *out_cache_collection) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_cache_collection); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list, + ccs_cache_collection_t in_cache_collection) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_cache_collection); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list) +{ + return ccs_list_release (io_list); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_list_object_release (ccs_list_object_t io_ccache) +{ + return cci_check_error (ccs_ccache_release ((ccs_ccache_t) io_ccache)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_list_object_compare_identifier (ccs_list_object_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_ccache_compare_identifier ((ccs_ccache_t) in_ccache, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidCCache, + ccErrInvalidCCacheIterator, + ccs_ccache_list_object_compare_identifier, + ccs_ccache_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_new_iterator (in_list, in_client_pipe, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_find_iterator (in_list, in_identifier, + (ccs_list_iterator_t *) out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list, + ccs_ccache_t in_ccache) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_push_front (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list) +{ + return ccs_list_release (io_list); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + return ccs_list_iterator_write (in_list_iterator, in_stream); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_iterator_clone (in_list_iterator, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator, + ccs_ccache_t *out_ccache) +{ + return ccs_list_iterator_next (io_list_iterator, (ccs_list_object_t *) out_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_release (io_list_iterator); +} + +#ifdef TARGET_OS_MAC +#pragma mark- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_list_object_release (ccs_list_object_t io_object) +{ + return cci_check_error (ccs_credentials_release ((ccs_credentials_t) io_object)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_list_object_compare_identifier (ccs_list_object_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_credentials_compare_identifier ((ccs_credentials_t) in_credentials, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidCredentials, + ccErrInvalidCredentialsIterator, + ccs_credentials_list_object_compare_identifier, + ccs_credentials_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_new_iterator (in_list, in_client_pipe, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_t *out_credentials) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_credentials); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_find_iterator (in_list, in_identifier, + (ccs_list_iterator_t *) out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list, + ccs_credentials_t in_credential) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_credential); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list) +{ + return ccs_list_release (io_list); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + return ccs_list_iterator_write (in_list_iterator, in_stream); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_iterator_clone (in_list_iterator, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator, + ccs_credentials_t *out_credential) +{ + return ccs_list_iterator_next (io_list_iterator, (ccs_list_object_t *) out_credential); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_release (io_list_iterator); +} + +#ifdef TARGET_OS_MAC +#pragma mark- +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_generic_list_iterator_invalidate (ccs_generic_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_invalidate (io_list_iterator); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_list.h b/krb5-1-7/src/ccapi/server/ccs_list.h new file mode 100644 index 000000000..e48d4c4f1 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_list.h @@ -0,0 +1,141 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 CCS_LIST_H +#define CCS_LIST_H + + +#include "ccs_types.h" + +cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list); + +cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list, + cci_identifier_t in_identifier, + ccs_cache_collection_t *out_cache_collection); + +cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list, + ccs_cache_collection_t in_cache_collection); + +cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list); + +cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list, + ccs_ccache_t in_ccache); + +cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list); + + +cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list); + +cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_t *out_credentials); + +cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list, + ccs_credentials_t in_credential); + +cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list); + + +cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator, + ccs_credentials_t *out_credential); + +cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_generic_list_iterator_invalidate (ccs_generic_list_iterator_t io_list_iterator); + +#endif /* CCS_LIST_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_list_internal.c b/krb5-1-7/src/ccapi/server/ccs_list_internal.c new file mode 100644 index 000000000..74bc45a6a --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_list_internal.c @@ -0,0 +1,677 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_list_internal.h" +#include "cci_array_internal.h" +#include "cci_identifier.h" +#include "ccs_server.h" + +typedef enum { + ccs_list_action_insert, + ccs_list_action_remove, + ccs_list_action_push_front +} ccs_list_action_enum; + +/* ------------------------------------------------------------------------ */ + +struct ccs_list_d { + cci_array_t objects; + cci_array_t iterators; + + cc_int32 object_not_found_err; + cc_int32 iterator_not_found_err; + + ccs_object_compare_identifier_t object_compare_identifier; +}; + +struct ccs_list_d ccs_list_initializer = { NULL, NULL, -1, -1, NULL }; + +/* ------------------------------------------------------------------------ */ + +struct ccs_list_iterator_d { + cci_identifier_t identifier; + ccs_pipe_t client_pipe; + ccs_list_t list; + cc_uint64 current; +}; + +struct ccs_list_iterator_d ccs_list_iterator_initializer = { NULL, CCS_PIPE_NULL, NULL, 0 }; + +static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator, + ccs_list_t in_list, + ccs_pipe_t in_client_pipe); + +static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator); + +static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator, + ccs_list_action_enum in_action, + cc_uint64 in_object_index); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_new (ccs_list_t *out_list, + cc_int32 in_object_not_found_err, + cc_int32 in_iterator_not_found_err, + ccs_object_compare_identifier_t in_object_compare_identifier, + ccs_object_release_t in_object_release) +{ + cc_int32 err = ccNoError; + ccs_list_t list = NULL; + + if (!out_list) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + list = malloc (sizeof (*list)); + if (list) { + *list = ccs_list_initializer; + list->object_not_found_err = in_object_not_found_err; + list->iterator_not_found_err = in_iterator_not_found_err; + list->object_compare_identifier = in_object_compare_identifier; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_array_new (&list->objects, in_object_release); + } + + if (!err) { + err = cci_array_new (&list->iterators, ccs_list_iterator_object_release); + } + + if (!err) { + *out_list = list; + list = NULL; + } + + ccs_list_release (list); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_release (ccs_list_t io_list) +{ + cc_int32 err = ccNoError; + + if (!err && io_list) { + cci_array_release (io_list->iterators); + cci_array_release (io_list->objects); + free (io_list); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_new_iterator (ccs_list_t io_list, + ccs_pipe_t in_client_pipe, + ccs_list_iterator_t *out_list_iterator) +{ + return cci_check_error (ccs_list_iterator_new (out_list_iterator, + io_list, + in_client_pipe)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_release_iterator (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t iterator = NULL; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_iterator (io_list, in_identifier, &iterator); + } + + if (!err) { + err = ccs_list_iterator_release (iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_count (ccs_list_t in_list, + cc_uint64 *out_count) +{ + cc_int32 err = ccNoError; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!out_count) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_count = cci_array_count (in_list->objects); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static ccs_list_iterator_t ccs_list_iterator_at_index (ccs_list_t in_list, + cc_uint64 in_index) +{ + return (ccs_list_iterator_t) cci_array_object_at_index (in_list->iterators, in_index); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_find_index (ccs_list_t in_list, + cci_identifier_t in_identifier, + cc_uint64 *out_object_index) +{ + cc_int32 err = ccNoError; + cc_int32 found = 0; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_object_index) { err = cci_check_error (ccErrBadParam); } + + if (!err && !found) { + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (in_list->objects); i++) { + cc_uint32 equal = 0; + cci_array_object_t object = cci_array_object_at_index (in_list->objects, i); + + err = in_list->object_compare_identifier (object, in_identifier, &equal); + + if (!err && equal) { + found = 1; + *out_object_index = i; + break; + } + } + } + + if (!err && !found) { + err = cci_check_error (in_list->object_not_found_err); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ +cc_int32 ccs_list_find (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + cc_uint64 i; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (in_list, in_identifier, &i); + } + + if (!err) { + *out_object = cci_array_object_at_index (in_list->objects, i); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_find_iterator_index (ccs_list_t in_list, + cci_identifier_t in_identifier, + cc_uint64 *out_object_index) +{ + cc_int32 err = ccNoError; + cc_int32 found = 0; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_object_index) { err = cci_check_error (ccErrBadParam); } + + if (!err && !found) { + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (in_list->iterators); i++) { + cc_uint32 equal = 0; + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (in_list, i); + + err = cci_identifier_compare (iterator->identifier, in_identifier, &equal); + + if (!err && equal) { + found = 1; + *out_object_index = i; + break; + } + } + } + + if (!err && !found) { + // Don't report this error to the log file. Non-fatal. + return in_list->object_not_found_err; + } else { + return cci_check_error (err); + } +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_find_iterator (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_iterator_t *out_list_iterator) +{ + cc_int32 err = ccNoError; + cc_uint64 i; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_iterator_index (in_list, in_identifier, &i); + } + + if (!err) { + *out_list_iterator = ccs_list_iterator_at_index (in_list, i); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_add (ccs_list_t io_list, + ccs_list_object_t in_object) +{ + cc_int32 err = ccNoError; + cc_uint64 add_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_object) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + add_index = cci_array_count (io_list->objects); + + err = cci_array_insert (io_list->objects, in_object, add_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, ccs_list_action_insert, add_index); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_remove (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cc_uint64 remove_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (io_list, in_identifier, &remove_index); + } + + if (!err) { + err = cci_array_remove (io_list->objects, remove_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, ccs_list_action_remove, remove_index); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_push_front (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cc_uint64 push_front_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (io_list, in_identifier, &push_front_index); + } + + if (!err) { + err = cci_array_push_front (io_list->objects, push_front_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, + ccs_list_action_push_front, + push_front_index); + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator, + ccs_list_t io_list, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = NULL; + + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + /* client_pipe may be NULL if the iterator exists for internal server use */ + + if (!err) { + list_iterator = malloc (sizeof (*list_iterator)); + if (list_iterator) { + *list_iterator = ccs_list_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&list_iterator->identifier); + } + + if (!err) { + list_iterator->list = io_list; + list_iterator->current = 0; + + err = cci_array_insert (io_list->iterators, + (cci_array_object_t) list_iterator, + cci_array_count (io_list->iterators)); + } + + if (!err && ccs_pipe_valid (in_client_pipe)) { + ccs_client_t client = NULL; + + err = ccs_pipe_copy (&list_iterator->client_pipe, in_client_pipe); + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + err = ccs_client_add_iterator (client, list_iterator); + } + } + + if (!err) { + *out_list_iterator = list_iterator; + list_iterator = NULL; + } + + ccs_list_iterator_release (list_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + + if (!in_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_list_iterator->identifier, + in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator, + ccs_list_iterator_t *out_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = NULL; + + if (!in_list_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_iterator_new (&list_iterator, + in_list_iterator->list, + in_list_iterator->client_pipe); + } + + if (!err) { + list_iterator->current = in_list_iterator->current; + + *out_list_iterator = list_iterator; + list_iterator = NULL; + } + + ccs_list_iterator_release (list_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator; + + if (!io_list_iterator) { err = ccErrBadParam; } + + if (!err && ccs_pipe_valid (list_iterator->client_pipe)) { + ccs_client_t client = NULL; + + err = ccs_server_client_for_pipe (list_iterator->client_pipe, &client); + + if (!err && client) { + /* if client object still has a reference to us, remove it */ + err = ccs_client_remove_iterator (client, list_iterator); + } + } + + if (!err) { + ccs_pipe_release (list_iterator->client_pipe); + cci_identifier_release (list_iterator->identifier); + free (io_list_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator) +{ + cc_int32 err = ccNoError; + + if (!err && io_list_iterator) { + cc_uint64 i = 0; + + if (ccs_list_find_iterator_index (io_list_iterator->list, + io_list_iterator->identifier, + &i) == ccNoError) { + /* cci_array_remove will call ccs_list_iterator_object_release */ + err = cci_array_remove (io_list_iterator->list->iterators, i); + } else { + cci_debug_printf ("Warning: iterator not in iterator list!"); + } + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_invalidate (ccs_list_iterator_t io_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator; + + if (!io_list_iterator) { err = ccErrBadParam; } + + if (!err) { + /* Client owner died. Remove client reference and then the iterator. */ + if (ccs_pipe_valid (list_iterator->client_pipe)) { + ccs_pipe_release (list_iterator->client_pipe); + list_iterator->client_pipe = CCS_PIPE_NULL; + } + + err = ccs_list_iterator_release (io_list_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) { + *out_object = cci_array_object_at_index (io_list_iterator->list->objects, + io_list_iterator->current); + } else { + err = ccIteratorEnd; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) { + *out_object = cci_array_object_at_index (io_list_iterator->list->objects, + io_list_iterator->current); + io_list_iterator->current++; + } else { + err = ccIteratorEnd; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator, + ccs_list_action_enum in_action, + cc_uint64 in_object_index) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* When the list changes adjust the current index so that */ + /* we don't unnecessarily skip or double count items */ + if (in_action == ccs_list_action_insert) { + if (io_list_iterator->current > in_object_index) { + io_list_iterator->current++; + } + + } else if (in_action == ccs_list_action_remove) { + if (io_list_iterator->current >= in_object_index) { + io_list_iterator->current--; + } + + } else if (in_action == ccs_list_action_push_front) { + if (io_list_iterator->current < in_object_index) { + io_list_iterator->current++; + } + + } else { + err = cci_check_error (ccErrBadParam); + } + } + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/server/ccs_list_internal.h b/krb5-1-7/src/ccapi/server/ccs_list_internal.h new file mode 100644 index 000000000..d659fbe10 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_list_internal.h @@ -0,0 +1,95 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_LIST_INTERNAL_H +#define CCS_LIST_INTERNAL_H + +#include "ccs_common.h" +#include "cci_array_internal.h" + +struct ccs_list_d; +typedef struct ccs_list_d *ccs_list_t; + +struct ccs_list_iterator_d; +typedef struct ccs_list_iterator_d *ccs_list_iterator_t; + +typedef cci_array_object_t ccs_list_object_t; +typedef cc_int32 (*ccs_object_release_t) (ccs_list_object_t); +typedef cc_int32 (*ccs_object_compare_identifier_t) (ccs_list_object_t, cci_identifier_t, cc_uint32 *); + +cc_int32 ccs_list_new (ccs_list_t *out_list, + cc_int32 in_object_not_found_err, + cc_int32 in_iterator_not_found_err, + ccs_object_compare_identifier_t in_object_compare_identifier, + ccs_object_release_t in_object_release); + +cc_int32 ccs_list_release (ccs_list_t io_list); + +cc_int32 ccs_list_new_iterator (ccs_list_t io_list, + ccs_pipe_t in_client_pipe, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_release_iterator (ccs_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_list_count (ccs_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_list_find (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_find_iterator (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_add (ccs_list_t io_list, + ccs_list_object_t in_object); + +cc_int32 ccs_list_remove (ccs_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_list_push_front (ccs_list_t io_list, + cci_identifier_t in_identifier); + + +cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_iterator_invalidate (ccs_list_iterator_t io_list_iterator); + +cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator); + +#endif /* CCS_LIST_INTERNAL_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_lock.c b/krb5-1-7/src/ccapi/server/ccs_lock.c new file mode 100644 index 000000000..639bd1732 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_lock.c @@ -0,0 +1,249 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" + +struct ccs_lock_d { + cc_uint32 type; + ccs_lock_state_t lock_state_owner; + ccs_callback_t callback; +}; + +struct ccs_lock_d ccs_lock_initializer = { 0, NULL, NULL }; + +static cc_int32 ccs_lock_invalidate_callback (ccs_callback_owner_t io_lock, + ccs_callback_t in_callback); + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_new (ccs_lock_t *out_lock, + cc_uint32 in_type, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_lock_state_t in_lock_state_owner) +{ + cc_int32 err = ccNoError; + ccs_lock_t lock = NULL; + + if (!out_lock ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_lock_state_owner ) { err = cci_check_error (ccErrBadParam); } + + if (in_type != cc_lock_read && + in_type != cc_lock_write && + in_type != cc_lock_upgrade && + in_type != cc_lock_downgrade) { + err = cci_check_error (ccErrBadLockType); + } + + if (!err) { + lock = malloc (sizeof (*lock)); + if (lock) { + *lock = ccs_lock_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + lock->type = in_type; + lock->lock_state_owner = in_lock_state_owner; + + err = ccs_callback_new (&lock->callback, + in_invalid_object_err, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) lock, + ccs_lock_invalidate_callback); + } + + if (!err) { + *out_lock = lock; + lock = NULL; + } + + ccs_lock_release (lock); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_release (ccs_lock_t io_lock) +{ + cc_int32 err = ccNoError; + + if (!err && io_lock) { + ccs_callback_release (io_lock->callback); + free (io_lock); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_invalidate_callback (ccs_callback_owner_t io_lock, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_lock ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccs_lock_t lock = (ccs_lock_t) io_lock; + + err = ccs_lock_state_invalidate_lock (lock->lock_state_owner, lock); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock) +{ + cc_int32 err = ccNoError; + + if (!io_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_reply_to_client (io_lock->callback, NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock, + cc_uint32 *out_pending) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_pending) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_is_pending (in_lock->callback, out_pending); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_type (ccs_lock_t in_lock, + cc_uint32 *out_lock_type) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_lock_type) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_lock_type = in_lock->type; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_read_lock) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_read_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_read_lock = (in_lock->type == cc_lock_read || + in_lock->type == cc_lock_downgrade); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_write_lock) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_write_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_write_lock = (in_lock->type == cc_lock_write || + in_lock->type == cc_lock_upgrade); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_for_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_is_for_client_pipe ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_is_for_client_pipe (in_lock->callback, in_client_pipe, + out_is_for_client_pipe); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t *out_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_client_pipe (in_lock->callback, out_client_pipe); + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_lock.h b/krb5-1-7/src/ccapi/server/ccs_lock.h new file mode 100644 index 000000000..d6f754860 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_lock.h @@ -0,0 +1,62 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_LOCK_H +#define CCS_LOCK_H + +#include "ccs_types.h" + +cc_int32 ccs_lock_new (ccs_lock_t *out_lock, + cc_uint32 in_type, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_lock_state_t in_lock_state_owner); + +cc_int32 ccs_lock_release (ccs_lock_t io_lock); + +cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock); + +cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock, + cc_uint32 *out_pending); + +cc_int32 ccs_lock_type (ccs_lock_t in_lock, + cc_uint32 *out_lock_type); + +cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_read_lock); + +cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_write_lock); + +cc_int32 ccs_lock_is_for_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe); + +cc_int32 ccs_lock_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t *out_client_pipe); + +#endif /* CCS_LOCK_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_lock_state.c b/krb5-1-7/src/ccapi/server/ccs_lock_state.c new file mode 100644 index 000000000..516a1e26a --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_lock_state.c @@ -0,0 +1,526 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" + +struct ccs_lock_state_d { + cc_int32 invalid_object_err; + cc_int32 pending_lock_err; + cc_int32 no_lock_err; + ccs_lock_array_t locks; + cc_uint64 first_pending_lock_index; +}; + +struct ccs_lock_state_d ccs_lock_state_initializer = { 1, 1, 1, NULL, 0 }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, + cc_int32 in_invalid_object_err, + cc_int32 in_pending_lock_err, + cc_int32 in_no_lock_err) +{ + cc_int32 err = ccNoError; + ccs_lock_state_t lock_state = NULL; + + if (!out_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + lock_state = malloc (sizeof (*lock_state)); + if (lock_state) { + *lock_state = ccs_lock_state_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_lock_array_new (&lock_state->locks); + } + + if (!err) { + lock_state->invalid_object_err = in_invalid_object_err; + lock_state->pending_lock_err = in_pending_lock_err; + lock_state->no_lock_err = in_no_lock_err; + + *out_lock_state = lock_state; + lock_state = NULL; + } + + ccs_lock_state_release (lock_state); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state) +{ + cc_int32 err = ccNoError; + + if (!err && io_lock_state) { + ccs_lock_array_release (io_lock_state->locks); + free (io_lock_state); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_add_pending_lock (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint64 *out_lock_index) +{ + cc_int32 err = ccNoError; + ccs_lock_t lock = NULL; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_new (&lock, in_lock_type, + io_lock_state->invalid_object_err, + in_client_pipe, in_reply_pipe, + io_lock_state); + } + + if (!err) { + err = ccs_lock_array_insert (io_lock_state->locks, lock, + ccs_lock_array_count (io_lock_state->locks)); + if (!err) { lock = NULL; /* take ownership */ } + } + + if (!err) { + *out_lock_index = ccs_lock_array_count (io_lock_state->locks) - 1; + } + + ccs_lock_release (lock); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_remove_lock (ccs_lock_state_t io_lock_state, + cc_uint64 in_lock_index) +{ + cc_int32 err = ccNoError; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_array_remove (io_lock_state->locks, in_lock_index); + + if (!err && in_lock_index < io_lock_state->first_pending_lock_index) { + io_lock_state->first_pending_lock_index--; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_grant_lock (ccs_lock_state_t io_lock_state, + cc_uint64 in_pending_lock_index) +{ + cc_int32 err = ccNoError; + ccs_lock_t pending_lock = NULL; + cc_uint32 type = 0; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + pending_lock = ccs_lock_array_object_at_index (io_lock_state->locks, + in_pending_lock_index); + if (!pending_lock || in_pending_lock_index < io_lock_state->first_pending_lock_index) { + err = cci_check_error (ccErrBadParam); + } + } + + if (!err) { + err = ccs_lock_type (pending_lock, &type); + } + + if (!err && (type == cc_lock_upgrade || type == cc_lock_downgrade)) { + /* lock upgrades or downgrades. Find the old lock and remove it. */ + ccs_pipe_t pending_client_pipe = CCS_PIPE_NULL; + + err = ccs_lock_client_pipe (pending_lock, &pending_client_pipe); + + if (!err) { + cc_uint64 i; + + for (i = 0; !err && i < io_lock_state->first_pending_lock_index; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 is_lock_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, pending_client_pipe, &is_lock_for_client); + + if (!err && is_lock_for_client) { + cci_debug_printf ("%s: Removing old lock %p at index %d to replace with pending lock %p.", + __FUNCTION__, lock, (int) i, pending_lock); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; in_pending_lock_index--; /* We removed one so back up an index */ } + break; + } + } + } + } + + if (!err) { + cc_uint64 new_lock_index = 0; + + err = ccs_lock_array_move (io_lock_state->locks, + in_pending_lock_index, + io_lock_state->first_pending_lock_index, + &new_lock_index); + if (!err) { io_lock_state->first_pending_lock_index++; } + } + + if (!err) { + err = ccs_lock_grant_lock (pending_lock); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_state_check_pending_lock (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_pending_lock_client_pipe, + cc_uint32 in_pending_lock_type, + cc_uint32 *out_grant_lock) +{ + cc_int32 err = ccNoError; + cc_uint32 is_write_locked = 0; + cc_uint32 client_has_lock = 0; + cc_uint32 other_clients_have_locks = 0; + cc_uint32 client_lock_type = 0; + cc_uint64 client_lock_index = 0; + cc_uint32 grant_lock = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_pending_lock_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_grant_lock ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = io_lock_state->first_pending_lock_index; + + for (i = 0; !err && i < lock_count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 lock_type = 0; + cc_uint32 lock_is_for_client = 0; + + err = ccs_lock_type (lock, &lock_type); + + if (!err) { + err = ccs_lock_is_for_client_pipe (lock, in_pending_lock_client_pipe, + &lock_is_for_client); + } + + if (!err) { + if (lock_type == cc_lock_write || lock_type == cc_lock_upgrade) { + is_write_locked = 1; + } + + if (!lock_is_for_client) { + other_clients_have_locks = 1; + + } else if (!client_has_lock) { /* only record type of 1st lock */ + client_has_lock = 1; + client_lock_type = lock_type; + client_lock_index = i; + } + } + } + } + + if (!err) { + cc_uint64 lock_count = io_lock_state->first_pending_lock_index; + + if (in_pending_lock_type == cc_lock_write) { + if (client_has_lock) { + err = cci_check_error (ccErrBadLockType); + } else { + grant_lock = (lock_count == 0); + } + + } else if (in_pending_lock_type == cc_lock_read) { + if (client_has_lock) { + err = cci_check_error (ccErrBadLockType); + } else { + grant_lock = !is_write_locked; + } + + } else if (in_pending_lock_type == cc_lock_upgrade) { + if (!client_has_lock || (client_lock_type != cc_lock_read && + client_lock_type != cc_lock_downgrade)) { + err = cci_check_error (ccErrBadLockType); + } else { + /* don't grant if other clients have read locks */ + grant_lock = !other_clients_have_locks; + } + + } else if (in_pending_lock_type == cc_lock_downgrade) { + if (!client_has_lock || (client_lock_type != cc_lock_write && + client_lock_type != cc_lock_upgrade)) { + err = cci_check_error (ccErrBadLockType); + } else { + /* downgrades can never block */ + grant_lock = 1; + } + } else { + err = cci_check_error (ccErrBadLockType); + } + } + + if (!err) { + *out_grant_lock = grant_lock; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_try_to_grant_pending_locks (ccs_lock_state_t io_lock_state) +{ + cc_int32 err = ccNoError; + cc_uint32 done = 0; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + /* Look at the pending locks and see if we can grant them. + * Note that downgrade locks mean we must check all pending locks each pass + * since a downgrade lock might be last in the list. */ + + while (!err && !done) { + cc_uint64 i; + cc_uint64 count = ccs_lock_array_count (io_lock_state->locks); + cc_uint32 granted_lock = 0; + + for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 lock_type = 0; + ccs_pipe_t client_pipe = CCS_PIPE_NULL; + cc_uint32 can_grant_lock_now = 0; + + err = ccs_lock_client_pipe (lock, &client_pipe); + + if (!err) { + err = ccs_lock_type (lock, &lock_type); + } + + if (!err) { + err = ccs_lock_state_check_pending_lock (io_lock_state, client_pipe, + lock_type, &can_grant_lock_now); + } + + if (!err && can_grant_lock_now) { + err = ccs_lock_status_grant_lock (io_lock_state, i); + if (!err) { granted_lock = 1; } + } + } + + if (!err && !granted_lock) { + /* we walked over all the locks and couldn't grant any of them */ + done = 1; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint32 in_block, + cc_uint32 *out_will_send_reply) +{ + cc_int32 err = ccNoError; + cc_uint32 can_grant_lock_now = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_send_reply ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Sanity check: if there are any pending locks for this client + * the client must have timed out waiting for our reply. Remove any + * existing pending locks for the client. */ + cc_uint64 i; + + for (i = io_lock_state->first_pending_lock_index; !err && i < ccs_lock_array_count (io_lock_state->locks); i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 has_pending_lock_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, in_client_pipe, &has_pending_lock_for_client); + + if (!err && has_pending_lock_for_client) { + cci_debug_printf ("WARNING %s: Removing unexpected pending lock %p at index %d.", + __FUNCTION__, lock, (int) i); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; /* We removed one so back up an index */ } + } + } + } + + if (!err) { + err = ccs_lock_state_check_pending_lock (io_lock_state, in_client_pipe, + in_lock_type, &can_grant_lock_now); + } + + if (!err) { + if (!can_grant_lock_now && (in_block == cc_lock_noblock)) { + err = cci_check_error (io_lock_state->pending_lock_err); + + } else { + cc_uint64 new_lock_index = 0; + + err = ccs_lock_status_add_pending_lock (io_lock_state, + in_client_pipe, + in_reply_pipe, + in_lock_type, + &new_lock_index); + + if (!err && can_grant_lock_now) { + err = ccs_lock_status_grant_lock (io_lock_state, new_lock_index); + + if (!err && (in_lock_type == cc_lock_downgrade)) { + /* downgrades can allow us to grant other locks */ + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + } + } + } + } + + if (!err) { + /* ccs_lock_state_add sends its replies via callback so caller shouldn't */ + *out_will_send_reply = 1; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + cc_uint32 found_lock = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + + /* Remove all locks for this client. + * There should only be one so warn if there are multiple */ + for (i = 0; !err && i < io_lock_state->first_pending_lock_index; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 is_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, in_client_pipe, &is_for_client); + + if (!err && is_for_client) { + if (found_lock) { + cci_debug_printf ("WARNING %s: Found multiple locks for client.", + __FUNCTION__); + } + + found_lock = 1; + + cci_debug_printf ("%s: Removing lock %p at index %d.", __FUNCTION__, lock, (int) i); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; /* We removed one so back up an index */ } + } + } + } + + if (!err && !found_lock) { + err = cci_check_error (io_lock_state->no_lock_err); + } + + if (!err) { + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_invalidate_lock (ccs_lock_state_t io_lock_state, + ccs_lock_t in_lock) +{ + cc_int32 err = ccNoError; + + if (!io_lock_state) { err = ccErrBadParam; } + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_lock_array_count (io_lock_state->locks); + + for (i = 0; !err && i < count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + + if (lock == in_lock) { + err = ccs_lock_status_remove_lock (io_lock_state, i); + + if (!err) { + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + break; + } + } + } + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_lock_state.h b/krb5-1-7/src/ccapi/server/ccs_lock_state.h new file mode 100644 index 000000000..c6b9bdb0d --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_lock_state.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_LOCK_STATE_H +#define CCS_LOCK_STATE_H + +#include "ccs_types.h" + +cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, + cc_int32 in_invalid_object_err, + cc_int32 in_pending_lock_err, + cc_int32 in_no_lock_err); + +cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state); + +cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint32 in_block, + cc_uint32 *out_will_send_reply); + +cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe); + +cc_int32 ccs_lock_state_invalidate_lock (ccs_lock_state_t io_lock_state, + ccs_lock_t in_lock); + +#endif /* CCS_LOCK_STATE_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_os_notify.h b/krb5-1-7/src/ccapi/server/ccs_os_notify.h new file mode 100644 index 000000000..572f749b1 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_os_notify.h @@ -0,0 +1,38 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 CCS_OS_NOTIFY_H +#define CCS_OS_NOTIFY_H + +#include "ccs_types.h" + +cc_int32 ccs_os_notify_cache_collection_changed (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_os_notify_ccache_changed (ccs_cache_collection_t io_cache_collection, + const char *in_ccache_name); + + +#endif /* CCS_OS_NOTIFY_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_os_pipe.h b/krb5-1-7/src/ccapi/server/ccs_os_pipe.h new file mode 100644 index 000000000..ade4b2edb --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_os_pipe.h @@ -0,0 +1,43 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_OS_PIPE_H +#define CCS_OS_PIPE_H + +#include "ccs_types.h" + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe); + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal); + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe); + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe); + +#endif /* CCS_OS_PIPE_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_os_server.h b/krb5-1-7/src/ccapi/server/ccs_os_server.h new file mode 100644 index 000000000..8212028d6 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_os_server.h @@ -0,0 +1,41 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_OS_SERVER_H +#define CCS_OS_SERVER_H + +#include "ccs_types.h" + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]); + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]); + +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]); + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_reply_stream); + +#endif /* CCS_OS_SERVER_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_pipe.c b/krb5-1-7/src/ccapi/server/ccs_pipe.c new file mode 100644 index 000000000..0a65a0aeb --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_pipe.c @@ -0,0 +1,59 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" +#include "ccs_os_pipe.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe) +{ + return ccs_os_pipe_valid (in_pipe); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal) +{ + return ccs_os_pipe_compare (in_pipe, in_compare_to_pipe, out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe) +{ + return ccs_os_pipe_copy (out_pipe, in_pipe); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe) +{ + return ccs_os_pipe_release (io_pipe); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_pipe.h b/krb5-1-7/src/ccapi/server/ccs_pipe.h new file mode 100644 index 000000000..daf6630b7 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_pipe.h @@ -0,0 +1,43 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_PIPE_H +#define CCS_PIPE_H + +#include "ccs_types.h" + +cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe); + +cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal); + +cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe); + +cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe); + +#endif /* CCS_PIPE_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_server.c b/krb5-1-7/src/ccapi/server/ccs_server.c new file mode 100644 index 000000000..c1bbe539a --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_server.c @@ -0,0 +1,402 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "ccs_os_server.h" + +/* Server Globals: */ + +cci_uuid_string_t g_server_id = NULL; +ccs_cache_collection_t g_cache_collection = NULL; +ccs_client_array_t g_client_array = NULL; + +/* ------------------------------------------------------------------------ */ + +int main (int argc, const char *argv[]) +{ + cc_int32 err = 0; + + if (!err) { + err = ccs_os_server_initialize (argc, argv); + } + + if (!err) { + err = cci_identifier_new_uuid (&g_server_id); + } + + if (!err) { + err = ccs_cache_collection_new (&g_cache_collection); + } + + if (!err) { + err = ccs_client_array_new (&g_client_array); + } + + if (!err) { + err = ccs_os_server_listen_loop (argc, argv); + } + + if (!err) { + free (g_server_id); + cci_check_error (ccs_cache_collection_release (g_cache_collection)); + cci_check_error (ccs_client_array_release (g_client_array)); + + err = ccs_os_server_cleanup (argc, argv); + } + + return cci_check_error (err) ? 1 : 0; +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier) +{ + return cci_check_error (cci_identifier_new (out_identifier, + g_server_id)); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_add_client (ccs_pipe_t in_connection_pipe) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!err) { + err = ccs_client_new (&client, in_connection_pipe); + } + + if (!err) { + cci_debug_printf ("%s: Adding client %p.", __FUNCTION__, client); + err = ccs_client_array_insert (g_client_array, + client, + ccs_client_array_count (g_client_array)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_remove_client (ccs_pipe_t in_connection_pipe) +{ + cc_int32 err = ccNoError; + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_client_array_count (g_client_array); + cc_uint32 found = 0; + + for (i = 0; !err && i < count; i++) { + ccs_client_t client = ccs_client_array_object_at_index (g_client_array, i); + + err = ccs_client_uses_pipe (client, in_connection_pipe, &found); + + if (!err && found) { + cci_debug_printf ("%s: Removing client %p.", __FUNCTION__, client); + err = ccs_client_array_remove (g_client_array, i); + break; + } + } + + if (!err && !found) { + cci_debug_printf ("WARNING %s() didn't find client in client list.", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_client_for_pipe (ccs_pipe_t in_client_pipe, + ccs_client_t *out_client) +{ + cc_int32 err = ccNoError; + ccs_client_t client_for_pipe = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_client ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_client_array_count (g_client_array); + + for (i = 0; !err && i < count; i++) { + ccs_client_t client = ccs_client_array_object_at_index (g_client_array, i); + cc_uint32 uses_pipe = 0; + + err = ccs_client_uses_pipe (client, in_client_pipe, &uses_pipe); + + if (!err && uses_pipe) { + client_for_pipe = client; + break; + } + } + } + + if (!err) { + *out_client = client_for_pipe; /* may be NULL if not found */ + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_client_is_valid (ccs_pipe_t in_client_pipe, + cc_uint32 *out_client_is_valid) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_client_is_valid ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + *out_client_is_valid = (client != NULL); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_server_request_demux (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t in_cache_collection, + enum cci_msg_id_t in_request_name, + cci_identifier_t in_request_identifier, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (in_request_name > cci_context_first_msg_id && + in_request_name < cci_context_last_msg_id) { + /* Note: context identifier doesn't need to match. + * Client just uses the identifier to detect server relaunch. */ + + if (!err) { + err = ccs_cache_collection_handle_message (in_client_pipe, + in_reply_pipe, + in_cache_collection, + in_request_name, + in_request_data, + out_will_block, + out_reply_data); + } + + } else if (in_request_name > cci_ccache_first_msg_id && + in_request_name < cci_ccache_last_msg_id) { + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_find_ccache (in_cache_collection, + in_request_identifier, + &ccache); + + if (!err) { + err = ccs_ccache_handle_message (in_client_pipe, + in_reply_pipe, + ccache, + in_cache_collection, + in_request_name, + in_request_data, + out_will_block, + out_reply_data); + } + + } else if (in_request_name > cci_ccache_iterator_first_msg_id && + in_request_name < cci_ccache_iterator_last_msg_id) { + ccs_ccache_iterator_t ccache_iterator = NULL; + + err = ccs_cache_collection_find_ccache_iterator (in_cache_collection, + in_request_identifier, + &ccache_iterator); + + if (!err) { + err = ccs_ccache_iterator_handle_message (ccache_iterator, + in_cache_collection, + in_request_name, + in_request_data, + out_reply_data); + } + + if (!err) { + *out_will_block = 0; /* can't block */ + } + + } else if (in_request_name > cci_credentials_iterator_first_msg_id && + in_request_name < cci_credentials_iterator_last_msg_id) { + ccs_credentials_iterator_t credentials_iterator = NULL; + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_find_credentials_iterator (in_cache_collection, + in_request_identifier, + &ccache, + &credentials_iterator); + + if (!err) { + err = ccs_credentials_iterator_handle_message (credentials_iterator, + ccache, + in_request_name, + in_request_data, + out_reply_data); + } + + if (!err) { + *out_will_block = 0; /* can't block */ + } + + } else { + err = ccErrBadInternalMessage; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_request) +{ + cc_int32 err = ccNoError; + enum cci_msg_id_t request_name = 0; + cci_identifier_t request_identifier = NULL; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_request ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_message_read_request_header (in_request, + &request_name, + &request_identifier); + } + + if (!err) { + cc_uint32 server_err = 0; + cc_uint32 valid = 0; + ccs_cache_collection_t cache_collection = g_cache_collection; + + server_err = cci_identifier_is_for_server (request_identifier, + g_server_id, + &valid); + + if (!server_err && !valid) { + server_err = cci_message_invalid_object_err (request_name); + } + + if (!server_err) { + + /* Monolithic server implementation would need to select + * cache collection here. Currently we only support per-user + * servers so we always use the same cache collection. */ + + server_err = ccs_server_request_demux (in_client_pipe, + in_reply_pipe, + cache_collection, + request_name, + request_identifier, + in_request, + &will_block, + &reply_data); + } + + if (server_err || !will_block) { + + /* send a reply now if the server isn't blocked on something */ + err = ccs_server_send_reply (in_reply_pipe, server_err, reply_data); + } + } + + cci_identifier_release (request_identifier); + k5_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe, + cc_int32 in_reply_err, + k5_ipc_stream in_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply = NULL; + + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_message_new_reply_header (&reply, in_reply_err); + } + + if (!err && in_reply_data && k5_ipc_stream_size (in_reply_data) > 0) { + err = k5_ipc_stream_write (reply, + k5_ipc_stream_data (in_reply_data), + k5_ipc_stream_size (in_reply_data)); + } + + if (!err) { + err = ccs_os_server_send_reply (in_reply_pipe, reply); + } + + k5_ipc_stream_release (reply); + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/ccs_server.h b/krb5-1-7/src/ccapi/server/ccs_server.h new file mode 100644 index 000000000..e059d86bc --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_server.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef CCS_SERVER_H +#define CCS_SERVER_H + +#include "ccs_types.h" + +cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier); + +cc_int32 ccs_server_add_client (ccs_pipe_t in_connection_pipe); + +cc_int32 ccs_server_remove_client (ccs_pipe_t in_connection_pipe); + +cc_int32 ccs_server_client_for_pipe (ccs_pipe_t in_client_pipe, + ccs_client_t *out_client); + +cc_int32 ccs_server_client_is_valid (ccs_pipe_t in_client_pipe, + cc_uint32 *out_client_is_valid); + +cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_request); + +cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe, + cc_int32 in_reply_err, + k5_ipc_stream in_reply_data); + +#endif /* CCS_SERVER_H */ diff --git a/krb5-1-7/src/ccapi/server/ccs_types.h b/krb5-1-7/src/ccapi/server/ccs_types.h new file mode 100644 index 000000000..aaea0336c --- /dev/null +++ b/krb5-1-7/src/ccapi/server/ccs_types.h @@ -0,0 +1,121 @@ +/* + * $Header$ + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 CCS_TYPES_H +#define CCS_TYPES_H + +#ifdef WIN32 +#pragma warning ( disable : 4068) +#endif + +#include "cci_types.h" + +struct cci_array_d; + +typedef struct cci_array_d *ccs_client_array_t; + +typedef struct cci_array_d *ccs_callback_array_t; + +typedef struct cci_array_d *ccs_callbackref_array_t; + +typedef struct cci_array_d *ccs_iteratorref_array_t; + +typedef struct cci_array_d *ccs_lock_array_t; + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ccs_os_pipe_t is IPC-specific so it's special cased here */ + +#if TARGET_OS_MAC +#include +typedef mach_port_t ccs_pipe_t; /* Mach IPC port */ +#define CCS_PIPE_NULL MACH_PORT_NULL + +#else + +#ifdef WIN32 +/* On Windows, a pipe is s struct: */ +#include "ccs_win_pipe.h" +typedef struct ccs_win_pipe_t* ccs_pipe_t; +#define CCS_PIPE_NULL (ccs_pipe_t)NULL + +#else +typedef int ccs_pipe_t; /* Unix domain socket */ +#define CCS_PIPE_NULL -1 + +#endif +#endif + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +struct ccs_callback_d; +typedef struct ccs_callback_d *ccs_callback_t; + +struct ccs_list_d; +struct ccs_list_iterator_d; + +/* Used for iterator array invalidate function */ +typedef struct ccs_list_iterator_d *ccs_generic_list_iterator_t; + +typedef struct ccs_list_d *ccs_cache_collection_list_t; + +typedef struct ccs_list_d *ccs_ccache_list_t; +typedef struct ccs_list_iterator_d *ccs_ccache_list_iterator_t; + +typedef struct ccs_list_d *ccs_credentials_list_t; +typedef struct ccs_list_iterator_d *ccs_credentials_list_iterator_t; + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +struct ccs_client_d; +typedef struct ccs_client_d *ccs_client_t; + +struct ccs_lock_d; +typedef struct ccs_lock_d *ccs_lock_t; + +struct ccs_lock_state_d; +typedef struct ccs_lock_state_d *ccs_lock_state_t; + +struct ccs_credentials_d; +typedef struct ccs_credentials_d *ccs_credentials_t; + +typedef ccs_credentials_list_iterator_t ccs_credentials_iterator_t; + +struct ccs_ccache_d; +typedef struct ccs_ccache_d *ccs_ccache_t; + +typedef ccs_ccache_list_iterator_t ccs_ccache_iterator_t; + +struct ccs_cache_collection_d; +typedef struct ccs_cache_collection_d *ccs_cache_collection_t; + +#endif /* CCS_TYPES_H */ diff --git a/krb5-1-7/src/ccapi/server/mac/CCacheServerInfo.plist b/krb5-1-7/src/ccapi/server/mac/CCacheServerInfo.plist new file mode 100644 index 000000000..e03d5f3ff --- /dev/null +++ b/krb5-1-7/src/ccapi/server/mac/CCacheServerInfo.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + CCacheServer + CFBundleGetInfoString + 4.1 + CFBundleIconFile + + CFBundleIdentifier + edu.mit.Kerberos.CCacheServer + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Kerberos Credentials Cache Server + CFBundlePackageType + APPL + CFBundleSignature + CCSa + CFBundleVersion + 0.0.1d1 + CFBundleShortVersionString + 5.5 + CFBundleGetInfoString + 5.5 Copyright MIT + KfMDisplayVersion + 5.5 Copyright MIT + KfMDisplayCopyright + Copyright MIT + NSHumanReadableCopyright + 5.5 Copyright MIT + LSBackgroundOnly + 1 + + diff --git a/krb5-1-7/src/ccapi/server/mac/ccs_os_notify.c b/krb5-1-7/src/ccapi/server/mac/ccs_os_notify.c new file mode 100644 index 000000000..920282316 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/mac/ccs_os_notify.c @@ -0,0 +1,80 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "ccs_os_notify.h" +#include + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_notify_cache_collection_changed (ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter (); + + if (center) { + CFNotificationCenterPostNotification (center, + kCCAPICacheCollectionChangedNotification, + NULL, NULL, TRUE); + } + } + + + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_notify_ccache_changed (ccs_cache_collection_t io_cache_collection, + const char *in_ccache_name) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter (); + CFStringRef name = CFStringCreateWithCString (kCFAllocatorDefault, + in_ccache_name, + kCFStringEncodingUTF8); + + if (center && name) { + CFNotificationCenterPostNotification (center, + kCCAPICCacheChangedNotification, + name, NULL, TRUE); + } + + if (name) { CFRelease (name); } + } + + return cci_check_error (err); +} diff --git a/krb5-1-7/src/ccapi/server/mac/ccs_os_pipe.c b/krb5-1-7/src/ccapi/server/mac/ccs_os_pipe.c new file mode 100644 index 000000000..91227676c --- /dev/null +++ b/krb5-1-7/src/ccapi/server/mac/ccs_os_pipe.c @@ -0,0 +1,81 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" +#include "ccs_os_pipe.h" +#include + +/* On Mac OS X ccs_pipe_t is a mach_port_t */ + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe) +{ + return MACH_PORT_VALID (in_pipe); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_pipe ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_pipe) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_equal = (in_pipe == in_compare_to_pipe); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe) +{ + cc_int32 err = 0; + + *out_pipe = in_pipe; + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) +{ + cc_int32 err = 0; + + /* Nothing to do here on Mac OS X */ + + return cci_check_error (err); +} + diff --git a/krb5-1-7/src/ccapi/server/mac/ccs_os_server.c b/krb5-1-7/src/ccapi/server/mac/ccs_os_server.c new file mode 100644 index 000000000..98bc6b30a --- /dev/null +++ b/krb5-1-7/src/ccapi/server/mac/ccs_os_server.c @@ -0,0 +1,98 @@ +/* + * $Header$ + * + * 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. + */ + +#include "ccs_common.h" + +#include +#include "k5_mig_server.h" +#include "ccs_os_server.h" + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_add_client (mach_port_t in_client_port) +{ + return cci_check_error (ccs_server_add_client (in_client_port)); +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_remove_client (mach_port_t in_client_port) +{ + return cci_check_error (ccs_server_remove_client (in_client_port)); +} + + +/* ------------------------------------------------------------------------ */ + +kern_return_t k5_ipc_server_handle_request (mach_port_t in_connection_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + return cci_check_error (ccs_server_handle_request (in_connection_port, + in_reply_port, + in_request_stream)); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) +{ + cc_int32 err = 0; + + openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH); + syslog (LOG_INFO, "Starting up."); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) +{ + cc_int32 err = 0; + + syslog (LOG_NOTICE, "Exiting."); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) +{ + return cci_check_error (k5_ipc_server_listen_loop ()); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_reply_stream) +{ + return cci_check_error (k5_ipc_server_send_reply (in_reply_pipe, + in_reply_stream)); +} diff --git a/krb5-1-7/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist b/krb5-1-7/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist new file mode 100644 index 000000000..34e697cb0 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist @@ -0,0 +1,35 @@ + + + + + Label + edu.mit.Kerberos.CCacheServer + LimitLoadToSessionType + Background + Program + /System/Library/CoreServices/CCacheServer.app/Contents/MacOS/CCacheServer + MachServices + + edu.mit.Kerberos.CCacheServer.ipcLookup + + HideUntilCheckIn + + ResetAtClose + + + edu.mit.Kerberos.CCacheServer.ipcService + + + EnableTransactions + + OnDemand + + ThrottleInterval + 0 + EnvironmentVariables + + CFFIXED_USER_HOME + /var/empty + + + diff --git a/krb5-1-7/src/ccapi/server/unix/Makefile.in b/krb5-1-7/src/ccapi/server/unix/Makefile.in new file mode 100644 index 000000000..09b199cae --- /dev/null +++ b/krb5-1-7/src/ccapi/server/unix/Makefile.in @@ -0,0 +1,15 @@ +thisconfigdir=../../.. +myfulldir=ccapi/server/unix +mydir=ccapi/server/unix +BUILDTOP=$(REL)..$(S)..$(S).. + +STLIBOBJS= +OBJS= +SRCS= + +all-unix:: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + +# +++ Dependency line eater +++ diff --git a/krb5-1-7/src/ccapi/server/win/Makefile.in b/krb5-1-7/src/ccapi/server/win/Makefile.in new file mode 100644 index 000000000..ea095a050 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/Makefile.in @@ -0,0 +1,110 @@ +# makefile: Constructs the Kerberos for Windows CCAPI server. + +#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/server/win, for making Makefile. +BUILDTOP=..\..\..\ +CCAPI = $(BUILDTOP)\CCAPI +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +SRVDIR = $(CCAPI)\server +SRVWIN = $(SRVDIR)\win +POSIX = $(BUILDTOP)\lib\krb5\posix +SRCTMP = $(SRVWIN)\srctmp + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +OBJS = $(OUTPRE)cci_array_internal.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_debugging.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)cci_os_debugging.$(OBJEXT) \ + $(OUTPRE)cci_os_identifier.$(OBJEXT) \ + $(OUTPRE)cci_stream.$(OBJEXT) \ + $(OUTPRE)ccs_array.$(OBJEXT) \ + $(OUTPRE)ccs_cache_collection.$(OBJEXT) \ + $(OUTPRE)ccs_callback.$(OBJEXT) \ + $(OUTPRE)ccs_ccache.$(OBJEXT) \ + $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_client.$(OBJEXT) \ + $(OUTPRE)ccs_credentials.$(OBJEXT) \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_list.$(OBJEXT) \ + $(OUTPRE)ccs_list_internal.$(OBJEXT) \ + $(OUTPRE)ccs_lock.$(OBJEXT) \ + $(OUTPRE)ccs_lock_state.$(OBJEXT) \ + $(OUTPRE)ccs_os_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_os_server.$(OBJEXT) \ + $(OUTPRE)ccs_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_reply_c.$(OBJEXT) \ + $(OUTPRE)ccs_request_proc.$(OBJEXT) \ + $(OUTPRE)ccs_server.$(OBJEXT) \ + $(OUTPRE)ccs_win_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_request_s.$(OBJEXT) \ + $(OUTPRE)ccutils.$(OBJEXT) \ + $(OUTPRE)init.$(OBJEXT) \ + $(OUTPRE)opts.$(OBJEXT) \ + $(OUTPRE)secure.$(OBJEXT) \ + $(OUTPRE)tls.$(OBJEXT) \ + $(OUTPRE)util.$(OBJEXT) \ + $(OUTPRE)win-utils.$(OBJEXT) \ + $(OUTPRE)WorkItem.$(OBJEXT) \ + $(OUTPRE)WorkQueue.$(OBJEXT) + +##### Options + +# Because all the sources are pulled together into the temp directory SRCTMP, +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \ + -I..\$(BUILDTOP)\util\et /I. +MIDLI = /I..\$(BUILDTOP)\include + +CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS + +##### Linker +LINK = link +LIBS = rpcrt4.lib advapi32.lib ws2_32.lib user32.lib +LFLAGS = /nologo $(LOPTS) + + +all:: Makefile copysrc midl $(OUTPRE)ccapiserver.exe finish + +ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_reply.idl + +copysrc : + echo "Copying all sources needed to build ccapiserver.exe to $(SRCTMP)" + if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP) + xcopy /D/Y $(CO)\*.* $(SRCTMP) + xcopy /D/Y $(COWIN)\*.* $(SRCTMP) + xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP) + xcopy /D/Y $(SRVDIR)\*.* $(SRCTMP) + xcopy /D/Y $(SRVWIN)\*.* $(SRCTMP) + cd $(SRCTMP) + if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE) + +midl : ccs_request.h ccs_reply.h + +$(OUTPRE)ccapiserver.exe: $(OBJS) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(LIBS) $(conlibsdll) $(conflags) + +finish : + @echo "Finished building ccapiserver.exe" + cd + +clean:: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.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 + if exist $(SRCTMP) rm -rf $(SRCTMP) diff --git a/krb5-1-7/src/ccapi/server/win/Server.sln b/krb5-1-7/src/ccapi/server/win/Server.sln new file mode 100644 index 000000000..64cc7f08c --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/Server.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1-7/src/ccapi/server/win/Server.vcproj b/krb5-1-7/src/ccapi/server/win/Server.vcproj new file mode 100644 index 000000000..39db361d8 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/Server.vcproj @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krb5-1-7/src/ccapi/server/win/WorkItem.cpp b/krb5-1-7/src/ccapi/server/win/WorkItem.cpp new file mode 100644 index 000000000..2e9ebcc93 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/WorkItem.cpp @@ -0,0 +1,126 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "assert.h" + +#pragma warning (disable : 4996) + +#include "win-utils.h" +#include "WorkItem.h" + +extern "C" { +#include "cci_debugging.h" + } + +// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted. + +void deleteBuffer(char** buf) { + if (*buf) { + delete [](*buf); + *buf = NULL; + } + } + +// WorkItem contains a CountedBuffer which must be deleted, +// so each WorkItem must be deleted. +WorkItem::WorkItem(k5_ipc_stream buf, WIN_PIPE* pipe, const long type, const long sst) +: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { } + +WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) { + + k5_ipc_stream _buf = NULL; + k5_ipc_stream_new(&_buf); + k5_ipc_stream_write(_buf, + k5_ipc_stream_data(item.payload()), + k5_ipc_stream_size(item.payload()) ); + WorkItem(_buf, item._pipe, item._rpcmsg, item._sst); + } + +WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { } + +WorkItem::~WorkItem() { + if (_buf) k5_ipc_stream_release(_buf); + if (_pipe) ccs_win_pipe_release(_pipe); + } + +const k5_ipc_stream WorkItem::take_payload() { + k5_ipc_stream temp = payload(); + _buf = NULL; + return temp; + } + +WIN_PIPE* WorkItem::take_pipe() { + WIN_PIPE* temp = pipe(); + _pipe = NULL; + return temp; + } + +WorkList::WorkList() { + assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400)); + } + +WorkList::~WorkList() { + // Delete any WorkItems in the queue: + WorkItem* item; + cci_debug_printf("%s", __FUNCTION__); + char buf[2048]; + char* pbuf = (char*)buf; + while (remove(&item)) { + cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf)); + delete item; + } + + DeleteCriticalSection(&cs); + } + +char* WorkItem::print(char* buf) { + sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst, + ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe)); + return buf; + } + +int WorkList::add(WorkItem* item) { + EnterCriticalSection(&cs); + wl.push_front(item); + LeaveCriticalSection(&cs); + return 1; + } + +int WorkList::remove(WorkItem** item) { + bool bEmpty; + + bEmpty = wl.empty() & 1; + + if (!bEmpty) { + EnterCriticalSection(&cs); + *item = wl.back(); + wl.pop_back(); + LeaveCriticalSection(&cs); + } + + return !bEmpty; + } \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/server/win/WorkQueue.cpp b/krb5-1-7/src/ccapi/server/win/WorkQueue.cpp new file mode 100644 index 000000000..f16ad117e --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/WorkQueue.cpp @@ -0,0 +1,61 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { + #include "cci_debugging.h" + } + +#include "WorkItem.h" + +WorkList worklist; + +/* C interfaces: */ +EXTERN_C bool worklist_isEmpty() { + return worklist.isEmpty(); + } + +EXTERN_C int worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const k5_ipc_stream stream, + const time_t serverStartTime) { + return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) ); + } + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + k5_ipc_stream* stream, + time_t* sst) { + WorkItem* item = NULL; + cc_int32 err = worklist.remove(&item); + + *rpcmsg = item->type(); + *pipe = item->take_pipe(); + *stream = item->take_payload(); + *sst = item->sst(); + delete item; + return err; + } + diff --git a/krb5-1-7/src/ccapi/server/win/WorkQueue.h b/krb5-1-7/src/ccapi/server/win/WorkQueue.h new file mode 100644 index 000000000..42d0cf207 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/WorkQueue.h @@ -0,0 +1,46 @@ +/* + * $Header$ + * + * Copyright 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 _work_queue_h +#define _work_queue_h + +#include "windows.h" +#include "cci_stream.h" +#include "ccs_pipe.h" + +EXTERN_C BOOL worklist_isEmpty(); + +EXTERN_C void worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const k5_ipc_stream stream, + const time_t serverStartTime); + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + k5_ipc_stream* stream, + time_t* serverStartTime); + +#endif // _work_queue_h \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/server/win/ccs_os_pipe.c b/krb5-1-7/src/ccapi/server/win/ccs_os_pipe.c new file mode 100644 index 000000000..95af378e7 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/ccs_os_pipe.c @@ -0,0 +1,64 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_common.h" +#include "ccs_os_pipe.h" +#include "ccs_win_pipe.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct. See ccs_win_pipe.h for details. */ + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe) { + return ccs_win_pipe_valid(in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t* out_pipe, ccs_pipe_t in_pipe) { + return ccs_win_pipe_copy( + out_pipe, + in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) { + return ccs_win_pipe_release(io_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t pipe_1, + ccs_pipe_t pipe_2, + cc_uint32 *out_equal) { + + return ccs_win_pipe_compare(pipe_1, pipe_2, out_equal); + } + diff --git a/krb5-1-7/src/ccapi/server/win/ccs_os_server.cpp b/krb5-1-7/src/ccapi/server/win/ccs_os_server.cpp new file mode 100644 index 000000000..99854d113 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/ccs_os_server.cpp @@ -0,0 +1,951 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "process.h" +#include "windows.h" + +extern "C" { +#include "ccs_common.h" +#include "ccs_os_server.h" +#include +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" +#include "cci_stream.h" + } + +#include "WorkQueue.h" +#include "util.h" +#include "opts.hxx" +#include "init.hxx" + +#pragma warning (disable : 4996) + +BOOL bListen = TRUE; /* Why aren't bool and true defined? */ +const char* sessID = NULL; /* The logon session we are running on behalf of. */ +time_t _sst = 0; +unsigned char* pszNetworkAddress = NULL; +unsigned char* pszStringBinding = NULL; +BOOL bRpcHandleInited = FALSE; +_RPC_ASYNC_STATE* rpcState = NULL; + +/* Thread procedures can take only one void* argument. We put all the args we want + to pass into this struct and then pass a pointer to the struct: */ +struct RpcRcvArgs { + char* networkAddress; + unsigned char* protocolSequence; + unsigned char* sessID; /* Used for this server's endpoint */ + unsigned char* uuid; /* Used for client's UUID */ + ParseOpts::Opts* opts; + RPC_STATUS status; + } rpcargs = { NULL, /* pszNetworkAddress */ + (unsigned char*)"ncalrpc", /* pszProtocolSequence */ + NULL, /* sessID placeholder */ + NULL, /* uuid placeholder */ + NULL }; /* Opts placeholder */ + +/* Command line format: + argv[0] Program name + argv[1] session ID to use + argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process + can be attached in debugger. + Any other value: continue + */ +#define N_FIXED_ARGS 3 +#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle + +/* Forward declarations: */ +void receiveLoop(void* rpcargs); +void connectionListener(void* rpcargs); +void Usage(const char* argv0); +void printError(TCHAR* msg); +void setMySST() {_sst = time(&_sst);} +time_t getMySST() {return _sst;} +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe); +void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*, + void* Context, + RPC_ASYNC_EVENT Event); +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context); +RPC_STATUS send_init(char* clientUUID); +//DWORD alloc_name(LPSTR* pname, LPSTR postfix); + + +/* The layout of the rest of this module: + + The four entrypoints defined in ccs_os_server.h: + ccs_os_server_initialize + cc_int32 ccs_os_server_cleanup + cc_int32 ccs_os_server_listen_loop + cc_int32 ccs_os_server_send_reply + + Other routines needed by those four. + */ + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) { + cc_int32 err = 0; + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + BOOL bAdjustedShutdown = FALSE; + HMODULE hKernel32 = GetModuleHandle("kernel32"); + + if (!err) { + sessID = argv[1]; + setMySST(); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + + PO.Parse(opts, argc, (char**)argv); + +// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */ + + if (hKernel32) { + typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD); + FP_SetProcessShutdownParameters pSetProcessShutdownParameters = + (FP_SetProcessShutdownParameters) + GetProcAddress(hKernel32, "SetProcessShutdownParameters"); + if (pSetProcessShutdownParameters) { + bAdjustedShutdown = pSetProcessShutdownParameters(100, 0); + } + } + cci_debug_printf("%s Shutdown Parameters", + bAdjustedShutdown ? "Adjusted" : "Did not adjust"); + + err = Init::Initialize(); + } + +// if (!err) { +// if (opts.bShutdown) { +// status = shutdown_server(opts.pszEndpoint); +// } +// } +// else { +// status = startup_server(opts); +// } + + if (err) { + Init::Cleanup(); + fprintf( stderr, "An error occured while %s the server (%u)\n", + opts.bShutdown ? "shutting down" : "starting/running", + err); + exit(cci_check_error (err)); + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) { + cc_int32 err = 0; + + cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]); + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +/* This function takes work items off the work queue and executes them. + * This is the one and only place where the multi-threaded Windows code + * calls into the single-threaded common code. + * + * The actual 'listening' for requests from clients happens after receiveloop + * establishes the RPC endpoint the clients will connect to and the RPC procedures + * put the work items into the work queue. + */ +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) { + cc_int32 err = 0; + uintptr_t threadStatus; + unsigned int loopCounter = 0; + + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + PO.Parse(opts, argc, (char**)argv); + + + //++ debug stuff + #define INFO_BUFFER_SIZE 32767 + TCHAR infoBuf[INFO_BUFFER_SIZE]; + DWORD bufCharCount = INFO_BUFFER_SIZE; + // Get and display the user name. + bufCharCount = INFO_BUFFER_SIZE; + if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") ); + //-- + + /* Sending the reply from within the request RPC handler doesn't seem to work. + So we listen for requests in a separate thread and put the requests in a + queue. */ + rpcargs.sessID = (unsigned char*)sessID; + rpcargs.opts = &opts; + threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs); + + /* We handle the queue entries here. Work loop: */ + while (TRUE) { + loopCounter++; + if (worklist_isEmpty() & 1) { + SleepEx(1000, TRUE); + } + else if (TRUE) { // Take next WorkItem from the queue: + k5_ipc_stream buf = NULL; + long rpcmsg = CCMSG_INVALID; + time_t serverStartTime = 0xDEADDEAD; + RPC_STATUS status = 0; + char* uuid = NULL; + k5_ipc_stream stream = NULL; + ccs_pipe_t pipe = NULL; + ccs_pipe_t pipe2 = NULL; + + if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) { + uuid = ccs_win_pipe_getUuid(pipe); +#if 0 + cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld", + __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime); +#endif + if (serverStartTime <= getMySST()) { + switch (rpcmsg) { + case CCMSG_CONNECT: { + cci_debug_printf(" Processing CONNECT"); + rpcargs.uuid = (unsigned char*)uuid; + + // Even if a disconnect message is received before this code finishes, + // it won't be dequeued and processed until after this code finishes. + // So we can add the client after starting the connection listener. + connectionListener((void*)&rpcargs); + status = rpcargs.status; + + if (!status) { + status = ccs_server_add_client(pipe); + } + if (!status) {status = send_connection_reply(pipe);} + break; + } + case CCMSG_DISCONNECT: { + cci_debug_printf(" Processing DISCONNECT"); + if (!status) { + status = ccs_server_remove_client(pipe); + } + break; + } + case CCMSG_REQUEST: + cci_debug_printf(" Processing REQUEST"); + ccs_pipe_copy(&pipe2, pipe); + // Dispatch message here, setting both pipes to the client UUID: + err = ccs_server_handle_request (pipe, pipe2, buf); + break; + case CCMSG_PING: + cci_debug_printf(" Processing PING"); + err = k5_ipc_stream_new (&stream); + err = k5_ipc_stream_write(stream, "This is a test of the emergency broadcasting system", 52); + err = ccs_os_server_send_reply(pipe, stream); + break; + default: + cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>", + rpcmsg, uuid); + break; + } + if (buf) k5_ipc_stream_release(buf); + /* Don't free uuid, which was allocated here. A pointer to it is in the + rpcargs struct which was passed to connectionListener which will be + received by ccapi_listen when the client exits. ccapi_listen needs + the uuid to know which client to disconnect. + */ + } + // Server's start time is different from what the client thinks. + // That means the server has rebooted since the client connected. + else { + cci_debug_printf("Whoops! Server has rebooted since client established connection."); + } + } + else {cci_debug_printf("Huh? Queue not empty but no item to remove.");} + } + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe, + k5_ipc_stream in_reply_stream) { + + /* ccs_pipe_t in_reply_pipe is a char* reply endpoint. + k5_ipc_stream in_reply_stream is the data to be sent. + */ + + cc_int32 err = 0; + char* uuid = ccs_win_pipe_getUuid(in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + + if (!err) { + err = send_init(uuid); // Sets RPC handle to be used. + } + + if (!err) { + RpcTryExcept { + long status; + ccs_rpc_request_reply( // make call with user message + CCMSG_REQUEST_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), + k5_ipc_stream_size(in_reply_stream), /* Length of buffer */ + (const unsigned char*)k5_ipc_stream_data(in_reply_stream), /* Data buffer */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + /* The calls to the remote procedures are complete. */ + /* Free whatever we allocated: */ + err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + + return cci_check_error (err); + } + + +/* Windows-specific routines: */ + +void Usage(const char* argv0) { + printf("Usage:\n"); + printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0); + printf(" CCAPI server process.\n"); + printf(" h|? whow usage message. <\n"); + } + +/* ------------------------------------------------------------------------ */ +/* The receive thread repeatedly issues RpcServerListen. + When a message arrives, it is handled in the RPC procedure. + */ +void receiveLoop(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + unsigned char* pszSecurity = NULL; + LPSTR endpoint = NULL; + LPSTR event_name = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + HANDLE hEvent = 0; + Init::InitInfo info; + + cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__); + + status = Init::Info(info); + + /* Build complete RPC endpoint using previous CCAPI implementation: */ + if (!status) { + if (!rcvargs->opts->pszEndpoint) { + if (!status) { + status = alloc_name(&endpoint, "ep", isNT()); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + } + + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + // We ignore any error opening the event because we do not know who started us. + // [Comment paraphrased from previous implementation, whence it was copied.] + } + } + else { + endpoint = rcvargs->opts->pszEndpoint; + } + } + + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + if (!status && isNT()) { + status = alloc_own_security_descriptor_NT(&psd); + } + + if (!status) { + status = RpcServerUseProtseqEp(rcvargs->protocolSequence, + rcvargs->opts->cMaxCalls, + (RPC_CSTR)endpoint, + rcvargs->opts->bDontProtect ? 0 : psd); // SD + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0); + } + + while (bListen && !status) { + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!info.isNT) { + status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + rcvargs->opts->cMaxCalls, + rcvargs->opts->bSecCallback ? + (RPC_IF_CALLBACK_FN*)sec_callback : 0 ); + } + + if (!status) { + status = RpcServerListen(rcvargs->opts->cMinCalls, + rcvargs->opts->cMaxCalls, + rcvargs->opts->fDontWait); + } + + if (!status) { + if (rcvargs->opts->fDontWait) { + if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization. + status = RpcMgmtWaitServerListen(); + } + } + } + + if (status) { // Cleanup in case of errors: + if (hEvent) CloseHandle(hEvent); + free_alloc_p(&event_name); + free_alloc_p(&psd); + if (endpoint && (endpoint != rcvargs->opts->pszEndpoint)) + free_alloc_p(&endpoint); + } + + _endthread(); + } // End receiveLoop + + +#if 0 + + return status; +} +#endif + + + +/* ------------------------------------------------------------------------ */ +/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_ + endpoint, ccapi_listen function to complete. If the call completes or gets an + RPC exception, it means the client has disappeared. + + A separate connectionListener is started for each client that has connected to the server. + */ + +void connectionListener(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + char* endpoint; + unsigned char* pszOptions = NULL; + unsigned char * pszUuid = NULL; + + endpoint = clientEndpoint((char*)rcvargs->uuid); + rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE)); + status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE)); + cci_debug_printf(""); + cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint); + + rpcState->UserInfo = rcvargs->uuid; + rpcState->NotificationType = RpcNotificationTypeApc; + rpcState->u.APC.NotificationRoutine = clientListener; + rpcState->u.APC.hThread = 0; + + /* [If in use] Free previous binding: */ + if (bRpcHandleInited) { + // Free previous binding (could have been used to call ccapi_listen + // in a different client thread). + // Don't check result or update status. + RpcStringFree(&pszStringBinding); + RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + bRpcHandleInited = FALSE; + } + + /* Set up binding to the client's endpoint: */ + if (!status) { + status = RpcStringBindingCompose( + pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (RPC_CSTR)endpoint, + pszOptions, + &pszStringBinding); + } + + /* Set the binding handle that will be used to bind to the server. */ + if (!status) { + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + } + if (!status) {bRpcHandleInited = TRUE;} + + RpcTryExcept { + cci_debug_printf(" Calling remote procedure ccapi_listen"); + ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status); + /* Asynchronous call will return immediately. */ + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + rcvargs->status = status; + } // End connectionListener + + +void RPC_ENTRY clientListener( + _RPC_ASYNC_STATE* pAsync, + void* Context, + RPC_ASYNC_EVENT Event + ) { + + ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL); + + cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!", + __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo); + + worklist_add( CCMSG_DISCONNECT, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +void printError( TCHAR* msg ) { + DWORD eNum; + TCHAR sysMsg[256]; + TCHAR* p; + + eNum = GetLastError( ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, eNum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + sysMsg, 256, NULL ); + + // Trim the end of the line and terminate it with a null + p = sysMsg; + while( ( *p > 31 ) || ( *p == 9 ) ) + ++p; + do { *p-- = 0; } while( ( p >= sysMsg ) && + ( ( *p == '.' ) || ( *p < 33 ) ) ); + + // Display the message + cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg); + } + + +RPC_STATUS send_init(char* clientUUID) { + RPC_STATUS status; + unsigned char * pszUuid = NULL; + unsigned char * pszOptions = NULL; + + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (unsigned char*)clientEndpoint(clientUUID), + pszOptions, + &pszStringBinding); + if (status) {return (status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + return (status); + } + +RPC_STATUS send_finish() { + RPC_STATUS status; + /* Can't shut down client -- it runs listen function which */ + /* server uses to detect the client going away. */ + + /* The calls to the remote procedures are complete. */ + /* Free the string and the binding handle */ + status = RpcStringFree(&pszStringBinding); // remote calls done; unbind + if (status) {return (status);} + + status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind + + return (status); + } + +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) { + char* uuid = ccs_win_pipe_getUuid (in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + RPC_STATUS status = send_init(uuid); + + RpcTryExcept { + ccs_rpc_connect_reply( // make call with user message + CCMSG_CONNECT_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), /* Server's session number = it's start time */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + status = send_finish(); + return (status); + } + +#if 0 +DWORD alloc_name(LPSTR* pname, LPSTR postfix) { + DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", sessID, postfix); + return 0; + } +#endif + +RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient, + LPTSTR pszClientName, + int iMaxLen) { + RPC_STATUS Status = RPC_S_OK; + RPC_BINDING_HANDLE hServer = NULL; + PTBYTE pszStringBinding = NULL; + PTBYTE pszClientNetAddr = NULL; + PTBYTE pszProtSequence = NULL; + + memset(pszClientName, 0, iMaxLen * sizeof(TCHAR)); + + __try { + // Create a partially bound server handle from the client handle. + Status = RpcBindingServerFromClient (hClient, &hServer); + if (Status != RPC_S_OK) __leave; + + // Get the partially bound server string binding and parse it. + Status = RpcBindingToStringBinding (hServer, + &pszStringBinding); + if (Status != RPC_S_OK) __leave; + + // String binding only contains protocol sequence and client + // address, and is not currently implemented for named pipes. + Status = RpcStringBindingParse (pszStringBinding, NULL, + &pszProtSequence, &pszClientNetAddr, + NULL, NULL); + if (Status != RPC_S_OK) + __leave; + int iLen = lstrlen(pszClientName) + 1; + if (iMaxLen < iLen) + Status = RPC_S_BUFFER_TOO_SMALL; + lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen); + } + __finally { + if (pszProtSequence) + RpcStringFree (&pszProtSequence); + + if (pszClientNetAddr) + RpcStringFree (&pszClientNetAddr); + + if (pszStringBinding) + RpcStringFree (&pszStringBinding); + + if (hServer) + RpcBindingFree (&hServer); + } + return Status; +} + +struct client_auth_info { + RPC_AUTHZ_HANDLE authz_handle; + unsigned char* server_principal; // need to RpcFreeString this + ULONG authn_level; + ULONG authn_svc; + ULONG authz_svc; +}; + +RPC_STATUS +GetClientId( + RPC_BINDING_HANDLE hClient, + char* client_id, + int max_len, + client_auth_info* info + ) +{ + RPC_AUTHZ_HANDLE authz_handle = 0; + unsigned char* server_principal = 0; + ULONG authn_level = 0; + ULONG authn_svc = 0; + ULONG authz_svc = 0; + RPC_STATUS status = 0; + + memset(client_id, 0, max_len); + + if (info) { + memset(info, 0, sizeof(client_auth_info)); + } + + status = RpcBindingInqAuthClient(hClient, &authz_handle, + info ? &server_principal : 0, + &authn_level, &authn_svc, &authz_svc); + if (status == RPC_S_OK) + { + if (info) { + info->server_principal = server_principal; + info->authz_handle = authz_handle; + info->authn_level = authn_level; + info->authn_svc = authn_svc; + info->authz_svc = authz_svc; + } + + if (authn_svc == RPC_C_AUTHN_WINNT) { + WCHAR* username = (WCHAR*)authz_handle; + int len = lstrlenW(username) + 1; + if (max_len < len) + status = RPC_S_BUFFER_TOO_SMALL; + _snprintf(client_id, max_len, "%S", username); + } else { + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + } + } + return status; +} + +char* +rpc_error_to_string( + RPC_STATUS status + ) +{ + switch(status) { + case RPC_S_OK: + return "OK"; + case RPC_S_INVALID_BINDING: + return "Invalid binding"; + case RPC_S_WRONG_KIND_OF_BINDING: + return "Wrong binding"; + case RPC_S_BINDING_HAS_NO_AUTH: + RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH); + return "Binding has no auth"; + default: + return "BUG: I am confused"; + } +} + +void +print_client_info( + RPC_STATUS peer_status, + const char* peer_name, + RPC_STATUS client_status, + const char* client_id, + client_auth_info* info + ) +{ + if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) { + cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name); + } else { + cci_debug_printf("%s Error %u getting Peer Name (%s)", + __FUNCTION__, peer_status, rpc_error_to_string(peer_status)); + } + + if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) { + if (info) { + cci_debug_printf("%s Client Auth Info" + "\tServer Principal: %s\n" + "\tAuthentication Level: %d\n" + "\tAuthentication Service: %d\n" + "\tAuthorization Service: %d\n", + __FUNCTION__, + info->server_principal, + info->authn_level, + info->authn_svc, + info->authz_svc); + } + cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id); + } else { + cci_debug_printf("%s Error getting Client Info (%u = %s)", + __FUNCTION__, client_status, rpc_error_to_string(client_status)); + } +} + +DWORD sid_check() { + DWORD status = 0; + HANDLE hToken_c = 0; + HANDLE hToken_s = 0; + PTOKEN_USER ptu_c = 0; + PTOKEN_USER ptu_s = 0; + DWORD len = 0; + BOOL bImpersonate = FALSE; + + // Note GetUserName will fail while impersonating at identify + // level. The workaround is to impersonate, OpenThreadToken, + // revert, call GetTokenInformation, and finally, call + // LookupAccountSid. + + // XXX - Note: This workaround does not appear to work. + // OpenThreadToken fails with error 1346: "Either a requid + // impersonation level was not provided or the provided + // impersonation level is invalid". + + status = RpcImpersonateClient(0); + + if (!status) { + bImpersonate = TRUE; + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c)) + status = GetLastError(); + } + + if (!status) { + status = RpcRevertToSelf(); + } + + if (!status) { + bImpersonate = FALSE; + + len = 0; + GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len); + if (len == 0) status = 1; + } + + if (!status) { + if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len)) + status = GetLastError(); + } + + if (!status) { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s)) + status = GetLastError(); + } + + if (!status) { + len = 0; + GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len); + if (len == 0) status = GetLastError(); + } + + if (!status) { + if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len)) + status = GetLastError(); + } + + if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid)) + status = RPC_S_ACCESS_DENIED; + +/* Cleanup: */ + if (!hToken_c && !bImpersonate) + cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status); + else if (!hToken_c) + cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status); + else if (bImpersonate) + cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status); + else if (!ptu_c) + cci_debug_printf("%s Failed to get client token user info (%u)", + __FUNCTION__, status); + else if (!hToken_s) + cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status); + else if (!ptu_s) + cci_debug_printf("%s Failed to get server token user info (%u)", + __FUNCTION__, status); + else if (status == RPC_S_ACCESS_DENIED) + cci_debug_printf("%s SID **does not** match!", __FUNCTION__); + else if (status == RPC_S_OK) + cci_debug_printf("%s SID matches!", __FUNCTION__); + else + if (status) { + cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status); + abort(); + } + + if (bImpersonate) RpcRevertToSelf(); + if (hToken_c && hToken_c != INVALID_HANDLE_VALUE) + CloseHandle(hToken_c); + if (ptu_c) LocalFree(ptu_c); + if (hToken_s && hToken_s != INVALID_HANDLE_VALUE) + CloseHandle(hToken_s); + if (ptu_s) LocalFree(ptu_s); + if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status); + return status; + } + +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context) { + char peer_name[1024]; + char client_name[1024]; + RPC_STATUS peer_status; + RPC_STATUS client_status; + + cci_debug_printf("%s", __FUNCTION__); + peer_status = GetPeerName(Context, peer_name, sizeof(peer_name)); + client_status = GetClientId(Context, client_name, sizeof(client_name), 0); + print_client_info(peer_status, peer_name, client_status, client_name, 0); + DWORD sid_status = sid_check(); + cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status); + return sid_status; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/krb5-1-7/src/ccapi/server/win/ccs_request_proc.c b/krb5-1-7/src/ccapi/server/win/ccs_request_proc.c new file mode 100644 index 000000000..8a0da03f4 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/ccs_request_proc.c @@ -0,0 +1,115 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ccs_request.h" // header file generated by MIDL compiler +#include "cci_debugging.h" +#include "WorkQueue.h" +#include "win-utils.h" +#include "ccs_win_pipe.h" + +void ccs_rpc_request( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Where client will listen for the reply */ + const long lenRequest, /* Length of buffer */ + const char pbRequest[], /* Data buffer */ + const long serverStartTime, /* Which server session we're talking to */ + long* return_status ) { /* Return code */ + + cc_int32 status = 0; + k5_ipc_stream stream; + DWORD* p = (DWORD*)(tspHandle); + WIN_PIPE* pipe = NULL; +#if 0 + cci_debug_printf("%s rpcmsg:%d; UUID:<%s> SST:<%s>", __FUNCTION__, rpcmsg, pszUUID, serverStartTime); +#endif + status = (rpcmsg != CCMSG_REQUEST) && (rpcmsg != CCMSG_PING); + + if (!status) { + status = k5_ipc_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = k5_ipc_stream_write (stream, pbRequest, lenRequest); + } + + pipe = ccs_win_pipe_new(pszUUID, *p); + worklist_add(rpcmsg, pipe, stream, serverStartTime); + *return_status = status; + } + + +void ccs_rpc_connect( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Data buffer */ + long* return_status ) { /* Return code */ + + DWORD* p = (DWORD*)(tspHandle); + WIN_PIPE* pipe = ccs_win_pipe_new(pszUUID, *p); +#if 0 + cci_debug_printf("%s; rpcmsg:%d; UUID: <%s>", __FUNCTION__, rpcmsg, pszUUID); +#endif + worklist_add( rpcmsg, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +// 'Authentication' is client setting a value in a file and the server +// returning that value plus one. +CC_UINT32 ccs_authenticate(const CC_CHAR* name) { + HANDLE hMap = 0; + PDWORD pvalue = 0; + CC_UINT32 result = 0; + DWORD status = 0; +#if 0 + cci_debug_printf("%s ( %s )", __FUNCTION__, name); +#endif + hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, (LPSTR)name); + status = !hMap; + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + status = !pvalue; + } + + if (!status) { + *pvalue += 1; + result = *pvalue; + } + + if (pvalue) { + UnmapViewOfFile(pvalue); + } + + if (hMap) CloseHandle(hMap); + return result; + } \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.c b/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.c new file mode 100644 index 000000000..4ef807dd5 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.c @@ -0,0 +1,165 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "assert.h" +#include +#include + +#include "ccs_win_pipe.h" +#include "cci_debugging.h" + +/* Ref: +struct ccs_win_pipe_t { + char* uuid; + HANDLE clientHandle; + } + */ + +/* ------------------------------------------------------------------------ */ + +struct ccs_win_pipe_t* ccs_win_pipe_new (const char* uuid, const HANDLE h) { + + cc_int32 err = ccNoError; + struct ccs_win_pipe_t* out_pipe = NULL; + char* uuidCopy = NULL; + + if (!err) { + if (!uuid) {err = cci_check_error(ccErrBadParam);} + } + + if (!err) { + uuidCopy = (char*)malloc(1+strlen(uuid)); + if (!uuidCopy) {err = cci_check_error(ccErrBadParam);} + strcpy(uuidCopy, uuid); + } + + if (!err) { + out_pipe = (struct ccs_win_pipe_t*)malloc(sizeof(struct ccs_win_pipe_t)); + if (!out_pipe) {err = cci_check_error(ccErrBadParam);} + out_pipe->uuid = uuidCopy; + out_pipe->clientHandle = h; + } +#if 0 + cci_debug_printf("0x%X = %s(%s, 0x%X)", out_pipe, __FUNCTION__, uuid, h); +#endif + return out_pipe; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe) { + + *out_pipe = + ccs_win_pipe_new( + ccs_win_pipe_getUuid (in_pipe), + ccs_win_pipe_getHandle(in_pipe) ); + + return (*out_pipe) ? ccNoError : ccErrBadParam; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_release(const WIN_PIPE* in_pipe) { + + cc_int32 err = ccNoError; + + if (!ccs_win_pipe_valid(in_pipe)) {err = cci_check_error(ccErrBadParam);} + + if (!err) { + if (!in_pipe->uuid) free(in_pipe->uuid); + if (!in_pipe) free(in_pipe); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe) { + + if (!in_pipe) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + if (!in_pipe->uuid) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + return TRUE; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* in_pipe_1, + const WIN_PIPE* in_pipe_2, + cc_uint32 *out_equal) { + + cc_int32 err = ccNoError; + int seq = 0; + *out_equal = FALSE; + + if (!ccs_win_pipe_valid(in_pipe_1)) {err = cci_check_error(ccErrBadParam);} + if (!ccs_win_pipe_valid(in_pipe_2)) {err = cci_check_error(ccErrBadParam);} + if (!out_equal) {err = cci_check_error(ccErrBadParam);} + + /* A disconnect doesn't have a tls* with it -- only the uuid. SO only + compare the uuids. + */ + if (!err) { + seq = strcmp( ccs_win_pipe_getUuid(in_pipe_1), + ccs_win_pipe_getUuid(in_pipe_2) ); + *out_equal = (seq == 0); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe) { + + char* result = NULL; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->uuid;} + + return result; + } + +/* ------------------------------------------------------------------------ */ + +HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe) { + + HANDLE result = NULL; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->clientHandle;} + + return result; + } diff --git a/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.h b/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.h new file mode 100644 index 000000000..3600d12af --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/ccs_win_pipe.h @@ -0,0 +1,69 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 _ccs_win_pipe_h_ +#define _ccs_win_pipe_h_ + +#include "windows.h" + +#include "CredentialsCache.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct containing a UUID and a handle. Both the + UUID and handle are supplied by the client. + + The UUID is used to build the client's reply endpoint. + + The handle is to the requesting client thread's thread local storage struct, + so that the client's one and only reply handler can put reply data where + the requesting thread will be able to see it. + */ + +struct ccs_win_pipe_t { + char* uuid; + HANDLE clientHandle; + }; + +typedef struct ccs_win_pipe_t WIN_PIPE; + +struct ccs_win_pipe_t* ccs_win_pipe_new(const char* uuid, const HANDLE h); + +cc_int32 ccs_win_pipe_release (const WIN_PIPE* io_pipe); + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* win_pipe_1, + const WIN_PIPE* win_pipe_2, + cc_uint32 *out_equal); + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe); + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe); + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe); +HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe); + +#endif // _ccs_win_pipe_h_ \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/server/win/workitem.h b/krb5-1-7/src/ccapi/server/win/workitem.h new file mode 100644 index 000000000..105380669 --- /dev/null +++ b/krb5-1-7/src/ccapi/server/win/workitem.h @@ -0,0 +1,48 @@ +#ifndef __WorkItem +#define __WorkItem + +#include +#include "windows.h" + +extern "C" { + #include "cci_stream.h" + #include "ccs_pipe.h" + } + +class WorkItem { +private: + k5_ipc_stream _buf; + WIN_PIPE* _pipe; + const long _rpcmsg; + const long _sst; +public: + WorkItem( k5_ipc_stream buf, + WIN_PIPE* pipe, + const long type, + const long serverStartTime); + WorkItem( const WorkItem&); + WorkItem(); + ~WorkItem(); + + const k5_ipc_stream payload() const {return _buf;} + const k5_ipc_stream take_payload(); + WIN_PIPE* take_pipe(); + WIN_PIPE* pipe() const {return _pipe;} + const long type() const {return _rpcmsg;} + const long sst() const {return _sst;} + char* print(char* buf); + }; + +class WorkList { +private: + std::list wl; + CRITICAL_SECTION cs; +public: + WorkList(); + ~WorkList(); + int add(WorkItem*); + int remove(WorkItem**); + bool isEmpty() {return wl.empty();} + }; + +#endif // __WorkItem \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/Makefile.in b/krb5-1-7/src/ccapi/test/Makefile.in new file mode 100644 index 000000000..9edab530c --- /dev/null +++ b/krb5-1-7/src/ccapi/test/Makefile.in @@ -0,0 +1,229 @@ +thisconfigdir=..$(S).. +myfulldir=ccapi$(S)test +mydir=ccapi$(S)test +BUILDTOP=..$(S).. +CCAPI=$(BUILDTOP)$(S)CCAPI + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +# Because all the sources are in ., +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I$(BUILDTOP) /I$(BUILDTOP)$(S)include /I$(BUILDTOP)$(S)include$(S)krb5 $(KFWINC) \ + -I$(BUILDTOP)$(S)util$(S)et /I. -I$(CCAPI)$(S)COMMON -I$(CCAPI)$(S)LIB + +# run with "make all" to create CCAPI tests in "/tmp/ccapi_test" +# run resulting tests with "sh test_ccapi.sh" + +##DOS##CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +##DOS## -D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS + +##DOS##WINH = cci_debugging.h \ +##DOS## ccs_reply.h \ +##DOS## ccs_request.h \ +##DOS## ccs_request_c.c \ +##DOS## cci_stream.h \ +##DOS## cci_types.h \ +##DOS## win-utils.h + +##DOS##LIBSRC=ccapi_ccache.c \ +##DOS## ccapi_ccache_iterator.c \ +##DOS## ccapi_context.c \ +##DOS## ccapi_context_change_time.c \ +##DOS## ccapi_ipc.c \ +##DOS## ccapi_credentials.c \ +##DOS## ccapi_credentials_iterator.c \ +##DOS## ccapi_string.c \ +##DOS## ccapi_v2.c + +##DOS##COMSRC=cci_cred_union.c \ +##DOS## cci_identifier.c \ +##DOS## cci_message.c \ +##DOS## cci_stream.c + +##DOS##COWSRC=cci_os_identifier.c + +SRCDIR = . +DSTROOT = $(SRCDIR) +OBJDIR = $(DSTROOT)$(S)ccapi_intermediates +DSTDIR = $(DSTROOT)$(S)ccapi_test +TESTDIR = $(DSTDIR)$(S)tests +SRCTMP = $(SRCDIR)\srctmp + +SCRIPT_NAME = test_ccapi.sh + +OBJECTS = $(OUTPRE)test_ccapi_ccache.$(OBJEXT) \ + $(OUTPRE)test_ccapi_check.$(OBJEXT) \ + $(OUTPRE)test_ccapi_constants.$(OBJEXT) \ + $(OUTPRE)test_ccapi_context.$(OBJEXT) \ + $(OUTPRE)test_ccapi_v2.$(OBJEXT) \ + $(OUTPRE)test_ccapi_globals.$(OBJEXT) \ + $(OUTPRE)test_ccapi_iterators.$(OBJEXT) \ + $(OUTPRE)test_ccapi_log.$(OBJEXT) \ + $(OUTPRE)test_ccapi_util.$(OBJEXT) + +PINGOBJS = $(OUTPRE)ccapi_ccache.$(OBJEXT) \ + $(OUTPRE)ccapi_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccapi_context.$(OBJEXT) \ + $(OUTPRE)ccapi_context_change_time.$(OBJEXT) \ + $(OUTPRE)ccapi_ipc.$(OBJEXT) \ + $(OUTPRE)ccapi_credentials.$(OBJEXT) \ + $(OUTPRE)ccapi_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccapi_string.$(OBJEXT) \ + $(OUTPRE)ccapi_v2.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_os_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)cci_stream.$(OBJEXT) \ + $(OUTPRE)ccs_request_c.$(OBJEXT) \ + $(OUTPRE)pingtest.$(OBJEXT) \ + $(OBJECTS) + +TESTALLOBJS=$(OUTPRE)main.$(OBJEXT) \ + $(OBJECTS) + +TEST_NAMES = test_cc_ccache_iterator_next \ + test_constants \ + test_cc_initialize \ + test_cc_credentials_iterator_next + +MORE_TESTS = test_cc_context_release \ + test_cc_context_get_change_time \ + test_cc_context_get_default_ccache_name \ + test_cc_context_open_ccache \ + test_cc_context_open_default_ccache \ + test_cc_context_create_ccache \ + test_cc_context_create_default_ccache \ + test_cc_context_create_new_ccache \ + test_cc_context_new_ccache_iterator \ + test_cc_context_compare \ + test_cc_ccache_release \ + test_cc_ccache_destroy \ + test_cc_ccache_set_default \ + test_cc_ccache_get_credentials_version \ + test_cc_ccache_get_name \ + test_cc_ccache_get_principal \ + test_cc_ccache_set_principal \ + test_cc_ccache_store_credentials \ + test_cc_ccache_remove_credentials \ + test_cc_ccache_new_credentials_iterator \ + test_cc_ccache_get_change_time \ + test_cc_ccache_get_last_default_time \ + test_cc_ccache_move \ + test_cc_ccache_compare \ + test_cc_ccache_get_kdc_time_offset \ + test_cc_ccache_set_kdc_time_offset \ + test_cc_ccache_clear_kdc_time_offset \ + test_cc_shutdown \ + test_cc_get_change_time \ + test_cc_open \ + test_cc_create \ + test_cc_close \ + test_cc_destroy \ + test_cc_get_cred_version \ + test_cc_get_name \ + test_cc_get_principal \ + test_cc_set_principal \ + test_cc_store \ + test_cc_remove_cred \ + test_cc_seq_fetch_NCs_begin \ + test_cc_seq_fetch_NCs_next \ + test_cc_seq_fetch_creds_begin \ + test_cc_seq_fetch_creds_next \ + test_cc_get_NC_info + + +##### Linker +LINK = link +LIBS = -lkrb5 +##DOS##LIBS = advapi32.lib rpcrt4.lib user32.lib ws2_32.lib ccapi.lib +LFLAGS = /nologo $(LOPTS) + +all-mac:: setup-test-dir pingtest simple_lock_test build-base build-tests link-tests copy-script success-message +all-windows:: setup-windows build-base $(OUTPRE)pingtest.exe build-tests build-testall copy-script success-message + +# compile base files used by all tests +build-base: $(PINGOBJS) + +##++ These two rules build each element of the list: +# compile each test +build-tests: $(TEST_NAMES) + @echo build-tests complete. + +$(TEST_NAMES): + @echo DBG: $@ + $(CC) $(ALL_CFLAGS) -Fe$(TESTDIR)$(S)$@.exe -Fd$(OBJDIR)$(S)$@.obj $@.c $(OBJECTS) $(LIBS) +# Clean .obj from .: + $(RM) $@.$(OBJEXT) +##-- These two rules build each element of the list. + +# Make a build directory +setup-test-dir: + @echo "Removing old destination directory... $(DSTDIR)" + if [ -d "$(DSTDIR)" ]; then chmod -R u+w "$(DSTDIR)" && rm -rf "$(DSTDIR)"; fi + mkdir -p "$(TESTDIR)" + if [ -d "$(OBJDIR)" ]; then chmod -R u+w "$(OBJDIR)" && rm -rf "$(OBJDIR)"; fi + mkdir -p "$(OBJDIR)" + +## The same trick as used in TEST_NAMES to run an action on each element ofthe list WINH: +setup-windows: $(WINH) $(LIBSRC) $(COMSRC) $(COWSRC) + if NOT exist $(TESTDIR) mkdir $(TESTDIR) + if NOT exist $(OBJDIR) mkdir $(OBJDIR) + set LINK = link + +# This rule assumes that nmake in ..\lib\win has already run. +# That is how ..\Makefile.in is set up. +$(WINH): + copy ..\lib\win\srctmp\$@ . + +$(LIBSRC): + copy ..\lib\$@ . + +$(COMSRC): + copy ..\common\$@ . + +$(COWSRC): + copy ..\common\win\$@ . + +# This rule assumes that nmake in ..\lib\win\ has already run. +$(OUTPRE)pingtest.exe: $(OBJECTS) $(PINGOBJS) +# There doesn't appear to be any way to examine a variable and return a value +# indicating whether a string is present in it. We use a perl script to +# check the LIB variable. If the path to ccapi.lib isn't present, the script +# deletes a.tmp and the following nmake actions correct LIB. + echo %%PATH%% > a.tmp + perl setlib.pl + if not exist a.tmp ( + @echo Adding ..\lib\win\srctmp to LIB + set LIB=%%LIB%%;..\lib\win\srctmp + ) + $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(PINGOBJS) $(LIBS) + $(LINK) $(LFLAGS) /map:$(@B)2.map /out:$(*B)2.exe $(conflags) $(PINGOBJS) $(LIBS) $(conlibsdll) + +link-tests: $(TEST_NAMES) + +build-testall: $(TEST_NAMES) $(OBJECTS) $(TESTALLOBJS) testall.exe + +testall.exe: + $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(TESTALLOBJS) $(LIBS) $(conslibdll) + + +simple_lock_test: + $(CC) -o $(TESTDIR)/simple_lock_test simple_lock_test.c $(LIBS) + +copy-script: + echo Copy script ... + cd + dir ccapi_test + cp $(SCRIPT_NAME) $(DSTDIR)$(S)$(SCRIPT_NAME) + +success-message: + @echo + @echo "CCAPI tests created in $(DSTDIR)" + +.PHONY: clean + +clean:: + -rm -rf "$(OBJDIR)" diff --git a/krb5-1-7/src/ccapi/test/Makefile.w32 b/krb5-1-7/src/ccapi/test/Makefile.w32 new file mode 100644 index 000000000..8c3da9515 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/Makefile.w32 @@ -0,0 +1,75 @@ +# . is ccapi/test. +CO = ..\common +COWIN = $(CO)\win +LIBDIR = ..\lib +LIBWIN = $(LIBDIR)\win +SRV = ..\server +SRVWIN = ..\server\win + +!include + +INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN) + +!if "$(CPU)" == "i386" +cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \ +$(INC) +!else +cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC) +!endif +LIBS = $(LIBWIN)\ccapi.lib + +DSTROOT = . +SRC = $(DSTROOT) +#OBJDIR = $(DSTROOT)\obj +OBJDIR = . +OBJEXT = obj +TESTDIR = $(DSTROOT)\tests +TESTEXT = exe +DSTDIR = $(DSTROOT)\ccapi_tests + +PINGOBJS = pingtest.obj +SIMPLEOBJS = simple_lock_test.obj + +comobjs = cci_debugging.obj cci_stream.obj +cowobjs = cci_os_debugging.obj +libobjs = ccs_request_c.obj + +#all: build-base simple_lock_test pingtest +all: build-base pingtest + +# compile base files used by all tests +build-base: $(comobjs) $(libobjs) $(srvobjs) + @echo "Base objects built." + +# rule to compile src files +.c.obj: + $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c + +$(comobjs) : $(CO)\$(*B).c + $(cc) $(cdebug) $(cflags) $(CO)\$(*B).c + +$(cowobjs) : $(COWIN)\$(*B).c + $(cc) $(cdebug) $(cflags) $(COWIN)\$(*B).c + +$(libobjs) : $(LIBWIN)\$(*B).c + $(cc) $(cdebug) $(cflags) $(LIBWIN)\$(*B).c + +#$(srvobjs) : $(SRVWIN)\$*.c +# $(cc) $(cdebug) $(cflags) $(SRVWIN)\$*.c + +simple_lock_test: simple_lock_test.obj $(OBJS) + @echo R3+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c + $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \ + $(LIBS) rpcrt4.lib + @echo R3- Built $(*B) in $(TESTDIR) + +pingtest: pingtest.obj + @echo R4+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c + $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) $(libobjs) $(srvobjs) \ + $(LIBS) rpcrt4.lib + @echo R4- Built $(*B) in $(TESTDIR) + +clean: + DEL *.$(OBJEXT) \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/Pingtest.sln b/krb5-1-7/src/ccapi/test/Pingtest.sln new file mode 100644 index 000000000..cf43a1e4f --- /dev/null +++ b/krb5-1-7/src/ccapi/test/Pingtest.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pingtest", "Pingtest.vcproj", "{04017001-3222-43C4-A03C-8423B5349276}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.ActiveCfg = Debug|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.Build.0 = Debug|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.ActiveCfg = Release|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1-7/src/ccapi/test/main.c b/krb5-1-7/src/ccapi/test/main.c new file mode 100644 index 000000000..d48601003 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/main.c @@ -0,0 +1,90 @@ +#include +#include + +// #include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" +#include "test_ccapi_iterators.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; +// cc_ccache_iterator_t cache_iterator = NULL; +// cc_credentials_iterator_t cred_iterator = NULL; + + fprintf(stdout, "Testing CCAPI against CCAPI v3 rev 8 documentation...\n"); + fprintf(stdout, "Warning: this test suite is woefully incomplete and unpolished.\n"); + + T_CCAPI_INIT; + + // *** ccapi v2 compat *** + err = check_cc_shutdown(); + err = check_cc_get_change_time(); + err = check_cc_open(); + err = check_cc_create(); + err = check_cc_close(); + err = check_cc_destroy(); + err = check_cc_get_cred_version(); + err = check_cc_get_name(); + err = check_cc_get_principal(); + err = check_cc_set_principal(); + err = check_cc_store(); + err = check_cc_remove_cred(); + err = check_cc_seq_fetch_NCs_begin(); + err = check_cc_seq_fetch_NCs_next(); + err = check_cc_seq_fetch_creds_begin(); + err = check_cc_seq_fetch_creds_next(); + err = check_cc_get_NC_info(); + + err = check_constants(); + + // *** cc_context *** + err = check_cc_initialize(); + err = check_cc_context_release(); + err = check_cc_context_get_change_time(); + err = check_cc_context_get_default_ccache_name(); + err = check_cc_context_open_ccache(); + err = check_cc_context_open_default_ccache(); + err = check_cc_context_create_ccache(); + err = check_cc_context_create_default_ccache(); + err = check_cc_context_create_new_ccache(); + err = check_cc_context_new_ccache_iterator(); + // err = check_cc_context_lock(); + // err = check_cc_context_unlock(); + err = check_cc_context_compare(); + + // *** cc_ccache *** + err = check_cc_ccache_release(); + err = check_cc_ccache_destroy(); + err = check_cc_ccache_set_default(); + err = check_cc_ccache_get_credentials_version(); + err = check_cc_ccache_get_name(); + err = check_cc_ccache_get_principal(); + err = check_cc_ccache_set_principal(); + err = check_cc_ccache_store_credentials(); + err = check_cc_ccache_remove_credentials(); + err = check_cc_ccache_new_credentials_iterator(); + // err = check_cc_ccache_lock(); + // err = check_cc_ccache_unlock(); + err = check_cc_ccache_get_change_time(); + err = check_cc_ccache_get_last_default_time(); + err = check_cc_ccache_move(); + err = check_cc_ccache_compare(); + err = check_cc_ccache_get_kdc_time_offset(); + err = check_cc_ccache_set_kdc_time_offset(); + err = check_cc_ccache_clear_kdc_time_offset(); + + // *** cc_ccache_iterator *** + err = check_cc_ccache_iterator_next(); + + // *** cc_credentials_iterator *** + err = check_cc_credentials_iterator_next(); + + fprintf(stdout, "\nFinished testing CCAPI. %d failure%s in total.\n", total_failure_count, (total_failure_count == 1) ? "" : "s"); + + return err; +} diff --git a/krb5-1-7/src/ccapi/test/pingtest.c b/krb5-1-7/src/ccapi/test/pingtest.c new file mode 100644 index 000000000..637f8ab18 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/pingtest.c @@ -0,0 +1,116 @@ +// pingtest.c +// +// Test RPC to server, with PING message, which exists for no other purpose than this test. + +#include +#include +#include +#include + +#include "cci_debugging.h" +#include "CredentialsCache.h" +#include "cci_stream.h" +#include "win-utils.h" + +#include "ccs_request.h" +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + + +extern cc_int32 cci_os_ipc_thread_init (void); +extern cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream); + +static DWORD dwTlsIndex; + +DWORD GetTlsIndex() {return dwTlsIndex;} + +RPC_STATUS send_test(char* endpoint) { + unsigned char* pszNetworkAddress = NULL; + unsigned char* pszOptions = NULL; + unsigned char* pszStringBinding = NULL; + unsigned char* pszUuid = NULL; + RPC_STATUS status; + + status = RpcStringBindingCompose(pszUuid, + (RPC_CSTR)"ncalrpc", + pszNetworkAddress, + (unsigned char*)endpoint, + pszOptions, + &pszStringBinding); + cci_debug_printf("%s pszStringBinding = %s", __FUNCTION__, pszStringBinding); + if (status) {return cci_check_error(status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &CLIENT_REQUEST_RPC_HANDLE); + if (status) {return cci_check_error(status);} + + status = RpcStringFree(&pszStringBinding); // Temp var no longer needed. + + if (!status) { + RpcTryExcept { + cci_debug_printf("%s calling remote procedure 'ccs_authenticate'", __FUNCTION__); + status = ccs_authenticate((CC_CHAR*)"DLLMAIN TEST!"); + cci_debug_printf(" ccs_authenticate returned %d", status); + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + cci_check_error(RpcBindingFree(&CLIENT_REQUEST_RPC_HANDLE)); + + return (status); + } + +int main( int argc, char *argv[]) { + cc_int32 err = 0; + cc_context_t context = NULL; + cci_stream_t send_stream = NULL; + cci_stream_t reply_stream = NULL; + char* message = "Hello, RPC!"; + + + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + +// send_test("krbcc.229026.0.ep"); + +#if 0 + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); +#endif + + if (!err) { + err = cci_os_ipc_thread_init(); + } + if (!err) { + err = cci_stream_new (&send_stream); + err = cci_stream_write(send_stream, message, 1+strlen(message)); + } + + if (!err) { + err = cci_os_ipc_msg(TRUE, send_stream, CCMSG_PING, &reply_stream); + } + Sleep(10*1000); + cci_debug_printf("Try finishing async call."); + + Sleep(INFINITE); + cci_debug_printf("main: return. err == %d", err); + + return 0; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/krb5-1-7/src/ccapi/test/setlib.pl b/krb5-1-7/src/ccapi/test/setlib.pl new file mode 100644 index 000000000..bba225066 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/setlib.pl @@ -0,0 +1,10 @@ +#!perl -w + +$b = "lib\\win\\srctmp"; +$a = $ENV{LIB}; +if (! ($a =~ /$b/) ) { + print "$b Not in LIB!\n"; + system("del a.tmp"); + } +else {print "$b in LIB.\n";} +exit(0); \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/simple_lock_test.c b/krb5-1-7/src/ccapi/test/simple_lock_test.c new file mode 100644 index 000000000..418d56ad0 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/simple_lock_test.c @@ -0,0 +1,91 @@ +/* + simple_lock_test.c + + Initializes two contexts in two different threads and tries to get read locks on both at the same time. + Hangs at line 24. +*/ +#include +#include + +#include "test_ccapi_log.h" + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +#ifdef TARGET_OS_MAC +#include +#include +#include +#else +#include "CredentialsCache.h" +#endif + + +void *other_thread (void) { + cc_int32 err; + cc_context_t context = NULL; + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + + log_error("thread: attempting lock. may hang. err == %d", err); + + if (!err) { + // hangs with cc_lock_read which should succeed immediately, but does not hang with write, upgrade, and downgrade, which fail immediately + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + if (context) { + cc_context_unlock(context); + cc_context_release(context); + context = NULL; + } + log_error("thread: return. err == %d", err); +} + + +int main (int argc, char *argv[]) { + cc_int32 err; + int status; + cc_context_t context = NULL; + +#ifdef TARGET_OS_MAC + pthread_t thread_id; +#endif + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + if (!err) { + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + log_error("main: initialized and read locked context. err == %d", err); + +#ifdef TARGET_OS_MAC + status = pthread_create (&thread_id, NULL, (void *) other_thread, NULL); + if (status != 0) { + log_error("pthread_create() returned %d", status); + exit(-1); + } + + pthread_join(thread_id, NULL); +#else + +#endif + + log_error("main: unlocking and releasing context. err == %d", err); + + if (context) { + log_error("main: calling cc_context_unlock"); + cc_context_unlock(context); + log_error("main: calling cc_context_release"); + cc_context_release(context); + context = NULL; + } + + log_error("main: return. err == %d", err); + +#if defined(_WIN32) + UNREFERENCED_PARAMETER(status); // no whining! +#endif + return 0; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c new file mode 100644 index 000000000..1698535fd --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_clear_kdc_time_offset(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_compare.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_compare.c new file mode 100644 index 000000000..6034a341d --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_compare.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_compare(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_destroy.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_destroy.c new file mode 100644 index 000000000..2b56f10c0 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_destroy.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_destroy(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_change_time.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_change_time.c new file mode 100644 index 000000000..323c66fe9 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_change_time.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_change_time(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_credentials_version.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_credentials_version.c new file mode 100644 index 000000000..7f3e71461 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_credentials_version.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_credentials_version(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c new file mode 100644 index 000000000..871342a10 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_kdc_time_offset(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_last_default_time.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_last_default_time.c new file mode 100644 index 000000000..a820d1385 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_last_default_time.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_last_default_time(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_name.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_name.c new file mode 100644 index 000000000..77e525a31 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_name.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_name(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_get_principal.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_principal.c new file mode 100644 index 000000000..8e110ed01 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_get_principal.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_principal(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_iterator_next.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_iterator_next.c new file mode 100644 index 000000000..ec81103d8 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_iterator_next.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_iterator_next(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_move.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_move.c new file mode 100644 index 000000000..37793181f --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_move.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_move(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c new file mode 100644 index 000000000..cd18693d4 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_new_credentials_iterator(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_release.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_release.c new file mode 100644 index 000000000..4a8e685bd --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_release.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_release(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_remove_credentials.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_remove_credentials.c new file mode 100644 index 000000000..c13a618ef --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_remove_credentials.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_remove_credentials(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_set_default.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_default.c new file mode 100644 index 000000000..6adf3e977 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_default.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_default(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c new file mode 100644 index 000000000..e15f246e9 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_kdc_time_offset(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_set_principal.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_principal.c new file mode 100644 index 000000000..4cc453402 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_set_principal.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_principal(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_ccache_store_credentials.c b/krb5-1-7/src/ccapi/test/test_cc_ccache_store_credentials.c new file mode 100644 index 000000000..53a6564c7 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_ccache_store_credentials.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_store_credentials(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_close.c b/krb5-1-7/src/ccapi/test/test_cc_close.c new file mode 100644 index 000000000..b3a5bc2ef --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_close.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_close(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_compare.c b/krb5-1-7/src/ccapi/test/test_cc_context_compare.c new file mode 100644 index 000000000..9b2626a5d --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_compare.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_compare(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_create_ccache.c b/krb5-1-7/src/ccapi/test/test_cc_context_create_ccache.c new file mode 100644 index 000000000..a616e1cab --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_create_ccache.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_ccache(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_create_default_ccache.c b/krb5-1-7/src/ccapi/test/test_cc_context_create_default_ccache.c new file mode 100644 index 000000000..aaad4ab57 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_create_default_ccache.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_default_ccache(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_create_new_ccache.c b/krb5-1-7/src/ccapi/test/test_cc_context_create_new_ccache.c new file mode 100644 index 000000000..c77d931ff --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_create_new_ccache.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_new_ccache(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_get_change_time.c b/krb5-1-7/src/ccapi/test/test_cc_context_get_change_time.c new file mode 100644 index 000000000..f98b2ce64 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_get_change_time.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_get_change_time(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_get_default_ccache_name.c b/krb5-1-7/src/ccapi/test/test_cc_context_get_default_ccache_name.c new file mode 100644 index 000000000..ffa8c2cbf --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_get_default_ccache_name.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_get_default_ccache_name(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_new_ccache_iterator.c b/krb5-1-7/src/ccapi/test/test_cc_context_new_ccache_iterator.c new file mode 100644 index 000000000..b7885de64 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_new_ccache_iterator.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_new_ccache_iterator(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_open_ccache.c b/krb5-1-7/src/ccapi/test/test_cc_context_open_ccache.c new file mode 100644 index 000000000..8e7e825b9 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_open_ccache.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_open_ccache(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_open_default_ccache.c b/krb5-1-7/src/ccapi/test/test_cc_context_open_default_ccache.c new file mode 100644 index 000000000..e6e72fa62 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_open_default_ccache.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_open_default_ccache(); + return err; +} + \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_cc_context_release.c b/krb5-1-7/src/ccapi/test/test_cc_context_release.c new file mode 100644 index 000000000..5510ab961 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_context_release.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_release(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_create.c b/krb5-1-7/src/ccapi/test/test_cc_create.c new file mode 100644 index 000000000..d591d47be --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_create.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_create(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_credentials_iterator_next.c b/krb5-1-7/src/ccapi/test/test_cc_credentials_iterator_next.c new file mode 100644 index 000000000..5ae961154 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_credentials_iterator_next.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_credentials_iterator_next(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_destroy.c b/krb5-1-7/src/ccapi/test/test_cc_destroy.c new file mode 100644 index 000000000..13eae7b00 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_destroy.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_destroy(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_get_NC_info.c b/krb5-1-7/src/ccapi/test/test_cc_get_NC_info.c new file mode 100644 index 000000000..fe72cbe35 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_get_NC_info.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_NC_info(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_get_change_time.c b/krb5-1-7/src/ccapi/test/test_cc_get_change_time.c new file mode 100644 index 000000000..8b031c1a3 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_get_change_time.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_change_time(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_get_cred_version.c b/krb5-1-7/src/ccapi/test/test_cc_get_cred_version.c new file mode 100644 index 000000000..865abf00f --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_get_cred_version.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_cred_version(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_get_name.c b/krb5-1-7/src/ccapi/test/test_cc_get_name.c new file mode 100644 index 000000000..b4efa40fc --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_get_name.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_name(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_get_principal.c b/krb5-1-7/src/ccapi/test/test_cc_get_principal.c new file mode 100644 index 000000000..f0078561d --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_get_principal.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_principal(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_initialize.c b/krb5-1-7/src/ccapi/test/test_cc_initialize.c new file mode 100644 index 000000000..bf2fcdc26 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_initialize.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_initialize(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_open.c b/krb5-1-7/src/ccapi/test/test_cc_open.c new file mode 100644 index 000000000..d3253d8a3 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_open.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_open(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_remove_cred.c b/krb5-1-7/src/ccapi/test/test_cc_remove_cred.c new file mode 100644 index 000000000..121ad1b52 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_remove_cred.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_remove_cred(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c new file mode 100644 index 000000000..0d08e9151 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_NCs_begin(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_next.c b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_next.c new file mode 100644 index 000000000..c941fd4fe --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_NCs_next.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_NCs_next(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_begin.c b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_begin.c new file mode 100644 index 000000000..16c0a72cb --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_begin.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_creds_begin(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_next.c b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_next.c new file mode 100644 index 000000000..eaaf451c4 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_seq_fetch_creds_next.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_creds_next(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_set_principal.c b/krb5-1-7/src/ccapi/test/test_cc_set_principal.c new file mode 100644 index 000000000..bfe9162bf --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_set_principal.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_set_principal(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_shutdown.c b/krb5-1-7/src/ccapi/test/test_cc_shutdown.c new file mode 100644 index 000000000..31c3d7c57 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_shutdown.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_shutdown(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_cc_store.c b/krb5-1-7/src/ccapi/test/test_cc_store.c new file mode 100644 index 000000000..7edc77715 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_cc_store.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_store(); + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi.bat b/krb5-1-7/src/ccapi/test/test_ccapi.bat new file mode 100644 index 000000000..2d5bec53b --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi.bat @@ -0,0 +1,43 @@ +# test_ccapi.bat + +@echo "\nBeginning test of CCAPI...\n" +@echo "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n" + +#run_test simple_lock_test + +teststest_constants.exe +tests\test_cc_initialize.exe +tests\test_cc_context_get_version.exe +exit 0 + +tests\test_cc_context_release.exe +tests\test_cc_context_get_change_time.exe +tests\test_cc_context_get_default_ccache_name.exe +tests\test_cc_context_open_ccache.exe +tests\test_cc_context_open_default_ccache.exe +tests\test_cc_context_create_ccache.exe +tests\test_cc_context_create_default_ccache.exe +tests\test_cc_context_create_new_ccache.exe +tests\test_cc_context_new_ccache_iterator.exe +tests\test_cc_context_compare.exe +tests\test_cc_ccache_release.exe +tests\test_cc_ccache_destroy.exe +tests\test_cc_ccache_set_default.exe +tests\test_cc_ccache_get_credentials_version.exe +tests\test_cc_ccache_get_name.exe +tests\test_cc_ccache_get_principal.exe +tests\test_cc_ccache_set_principal.exe +tests\test_cc_ccache_store_credentials.exe +tests\test_cc_ccache_remove_credentials.exe +tests\test_cc_ccache_new_credentials_iterator.exe +tests\test_cc_ccache_get_change_time.exe +tests\test_cc_ccache_get_last_default_time.exe +tests\test_cc_ccache_move.exe +tests\test_cc_ccache_compare.exe +tests\test_cc_ccache_get_kdc_time_offset.exe +tests\test_cc_ccache_set_kdc_time_offset.exe +tests\test_cc_ccache_clear_kdc_time_offset.exe +tests\test_cc_ccache_iterator_next.exe +tests\test_cc_credentials_iterator_next.exe + +@echo "Finished testing CCAPI." diff --git a/krb5-1-7/src/ccapi/test/test_ccapi.sh b/krb5-1-7/src/ccapi/test/test_ccapi.sh new file mode 100644 index 000000000..c8959d688 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# run with ./test-ccapi.sh to run CCAPI tests + +TEST_DIR="tests" +failure_count=0 + +function run_test { + if [[ -e $TEST_DIR/$1 ]]; then + ./$TEST_DIR/$1 + failure_count=`expr $failure_count + $?` + fi +} + +printf "\nBeginning test of CCAPI...\n" +printf "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n" + +run_test simple_lock_test + +run_test test_constants + +run_test test_cc_initialize +run_test test_cc_context_release +run_test test_cc_context_get_change_time +run_test test_cc_context_get_default_ccache_name +run_test test_cc_context_open_ccache +run_test test_cc_context_open_default_ccache +run_test test_cc_context_create_ccache +run_test test_cc_context_create_default_ccache +run_test test_cc_context_create_new_ccache +run_test test_cc_context_new_ccache_iterator +run_test test_cc_context_compare + +run_test test_cc_ccache_release +run_test test_cc_ccache_destroy +run_test test_cc_ccache_set_default +run_test test_cc_ccache_get_credentials_version +run_test test_cc_ccache_get_name +run_test test_cc_ccache_get_principal +run_test test_cc_ccache_set_principal +run_test test_cc_ccache_store_credentials +run_test test_cc_ccache_remove_credentials +run_test test_cc_ccache_new_credentials_iterator +run_test test_cc_ccache_get_change_time +run_test test_cc_ccache_get_last_default_time +run_test test_cc_ccache_move +run_test test_cc_ccache_compare +run_test test_cc_ccache_get_kdc_time_offset +run_test test_cc_ccache_set_kdc_time_offset +run_test test_cc_ccache_clear_kdc_time_offset + +run_test test_cc_ccache_iterator_next + +run_test test_cc_credentials_iterator_next + +run_test test_cc_shutdown +run_test test_cc_get_change_time +run_test test_cc_open +run_test test_cc_create +run_test test_cc_close +run_test test_cc_destroy +run_test test_cc_get_cred_version +run_test test_cc_get_name +run_test test_cc_get_principal +run_test test_cc_set_principal +run_test test_cc_store +run_test test_cc_remove_cred +run_test test_cc_seq_fetch_NCs_begin +run_test test_cc_seq_fetch_NCs_next +run_test test_cc_seq_fetch_creds_begin +run_test test_cc_seq_fetch_creds_next +run_test test_cc_get_NC_info + +printf "\nFinished testing CCAPI. $failure_count failures in total.\n" + +exit 0 \ No newline at end of file diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_ccache.c b/krb5-1-7/src/ccapi/test/test_ccapi_ccache.c new file mode 100644 index 000000000..64a70e3c2 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_ccache.c @@ -0,0 +1,2037 @@ + +#include +#include +#include +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_release(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_release"); + + #ifndef cc_ccache_release + log_error("cc_ccache_release is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + + + if (!err) { + check_once_cc_ccache_release(context, ccache, ccNoError, NULL); + ccache = NULL; + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_release */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidCCache, + }; + + cc_string_t name = NULL; + + err = cc_ccache_get_name(ccache, &name); + err = cc_ccache_release(ccache); + ccache = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_release + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_context_open_ccache(context, name->data, &ccache); + } + check_if(err == ccErrCCacheNotFound, "released ccache was actually destroyed instead"); + + if (ccache) { cc_ccache_destroy(ccache); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_release */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_destroy(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_destroy"); + + #ifndef cc_ccache_destroy + log_error("cc_ccache_destroy is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + + + if (!err) { + check_once_cc_ccache_destroy(context, ccache, ccNoError, NULL); + ccache = NULL; + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_destroy */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidCCache, + }; + + cc_string_t name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_destroy + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_get_name(ccache, &name); + err = cc_ccache_destroy(ccache); + ccache = NULL; + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_context_open_ccache(context, name->data, &ccache); + } + check_if(err != ccErrCCacheNotFound, "destroyed ccache was actually released instead"); + + if (ccache) { cc_ccache_destroy(ccache); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_destroy */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_set_default(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_default"); + + #ifndef cc_ccache_set_default + log_error("cc_ccache_set_default is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + // try when it's the only ccache (already default) + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's the only ccache (already default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try when it's not the only ccache (and not default) + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and not default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try when it's not the only ccache (and already default) + if (!err) { + err = cc_context_open_default_ccache(context, &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and already default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_set_default */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[3] = { + ccNoError, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + cc_ccache_t default_ccache = NULL; + cc_string_t name = NULL; + cc_string_t default_name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_default + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_default(ccache); + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (!err) { + err = cc_context_open_default_ccache(context, &default_ccache); + } + if (!err) { + err = cc_ccache_get_name(default_ccache, &default_name); + } + if (name && default_name) { + check_if(strcmp(name->data, default_name->data), NULL); + } + else { + check_if(1, "cc_ccache_get_name failed"); + } + + if (default_ccache) { cc_ccache_release(default_ccache); } + //if (ccache) { cc_ccache_destroy(ccache); } // ccache is released by the caller + if (default_name) { cc_string_release(default_name); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_set_default */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_credentials_version(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_credentials_version"); + + #ifndef cc_ccache_get_credentials_version + log_error("cc_ccache_get_credentials_version is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + // try one created with v5 creds + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v5, ccNoError, "v5 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + // try it with added v4 creds + if (!err) { + err = cc_ccache_set_principal(ccache, cc_credentials_v4, "foo@BAR.ORG"); + } + if (!err) { + check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v5 with v4 creds added"); + } + else { + log_error("cc_ccache_set_principal failed, can't complete test"); + failure_count++; + } + + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + err = ccNoError; + + // try one created with v4 creds + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4, ccNoError, "v4 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + // try it with added v5 creds + if (!err) { + err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); + } + if (!err) { + check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v4 with v5 creds added"); + } + else { + log_error("cc_ccache_set_principal failed, can't complete test"); + failure_count++; + } + + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_get_credentials_version */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + cc_uint32 stored_cred_vers = 0; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_credentials_version + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_get_credentials_version(ccache, &stored_cred_vers); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(stored_cred_vers != expected_cred_vers, NULL); + } + + #endif /* cc_ccache_get_credentials_version */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_name(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_name"); + + #ifndef cc_ccache_get_name + log_error("cc_ccache_get_name is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // try with unique ccache (which happens to be default) + if (!err) { + err = cc_context_create_ccache(context, "0", cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_name(ccache, "0", ccNoError, "unique ccache (which happens to be default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // try with unique ccache (which is not default) + if (!err) { + err = cc_context_create_ccache(context, "1", cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_name(ccache, "1", ccNoError, "unique ccache (which is not default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_ccache_get_name(ccache, NULL, ccErrBadParam, "NULL param"); + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_name */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + cc_string_t stored_name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_name + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_name == NULL) { // we want to try with a NULL param + err = cc_ccache_get_name(ccache, NULL); + } + else { + err = cc_ccache_get_name(ccache, &stored_name); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_name->data, expected_name), NULL); + } + + if (stored_name) { cc_string_release(stored_name); } + + #endif /* cc_ccache_get_name */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, + cc_uint32 cred_vers, + const char *expected_principal, + cc_int32 expected_err, + const char *description) { + cc_int32 err = ccNoError; + cc_string_t stored_principal = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrNoMem, + ccErrBadCredentialsVersion, + ccErrBadParam, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_principal + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_principal == NULL) { // we want to try with a NULL param + err = cc_ccache_get_principal(ccache, cred_vers, NULL); + } + else { + err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_principal->data, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal->data); + } + + if (stored_principal) { cc_string_release(stored_principal); } + + #endif /* cc_ccache_get_principal */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_principal(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_principal"); + + #ifndef cc_ccache_get_principal + log_error("cc_ccache_get_principal is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // try with krb5 principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo/BAR@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, "foo/BAR@BAZ.ORG", ccNoError, "trying to get krb5 princ for krb5 ccache"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // try with krb4 principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo.BAR@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_principal(ccache, cc_credentials_v4, "foo.BAR@BAZ.ORG", ccNoError, "trying to get krb4 princ for krb4 ccache"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + // cc_ccache_t doesn't have any concept of the difference between a v4 and v5 principal + check_once_cc_ccache_get_principal(ccache, cc_credentials_v4_v5, "foo.BAR@BAZ.ORG", + ccErrBadCredentialsVersion, + "passing cc_credentials_v4_v5 (shouldn't be allowed)"); + check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "passed null out param"); + } + + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_principal */ + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_principal(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_principal"); + + #ifndef cc_ccache_set_principal + log_error("cc_ccache_set_principal is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // bad params + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v4_v5, "foo/BAZ@BAR.ORG", ccErrBadCredentialsVersion, "cc_credentials_v4_v5 (not allowed)"); + check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL principal"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + + // empty ccache + + // replace v5 only ccache's principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "replace v5 only ccache's principal (empty ccache)"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + // add v4 principal to v5 only ccache + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "add v4 principal to v5 only ccache (empty ccache)"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + // replace v4 only ccache's principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "replace v4 only ccache's principal (empty ccache)"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + // add v5 principal to v4 only ccache + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "add v5 principal to v4 only ccache (empty ccache)"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + // with credentials + + // replace v5 only ccache's principal + + // add v4 principal to v5 only ccache + + // replace v4 only ccache's principal + + // add v5 principal to v4 only ccache + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_set_principal */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_string_t stored_principal = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrNoMem, + ccErrInvalidCCache, + ccErrBadCredentialsVersion, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_principal + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_principal(ccache, cred_vers, in_principal); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); + } + + // compare stored with input + if (!err) { + check_if(strcmp(stored_principal->data, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal->data); + } + + if (stored_principal) { cc_string_release(stored_principal); } + + #endif /* cc_ccache_set_principal */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_store_credentials(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_union creds_union; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_store_credentials"); + + #ifndef cc_ccache_store_credentials + log_error("cc_ccache_store_credentials is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // cred with matching version and realm + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccNoError, "ok creds"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + + // try with bad params + check_once_cc_ccache_store_credentials(ccache, NULL, ccErrBadParam, "NULL creds param"); + + // invalid creds + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + if (creds_union.credentials.credentials_v5->client) { + free(creds_union.credentials.credentials_v5->client); + creds_union.credentials.credentials_v5->client = NULL; + } + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadParam, "invalid creds (NULL client string)"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + + // bad creds version + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + creds_union.version = cc_credentials_v4_v5; + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4_v5 creds (invalid) into a ccache with only v5 princ"); + creds_union.version = cc_credentials_v4; + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4 creds into a ccache with only v5 princ"); + creds_union.version = cc_credentials_v5; + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCCache, "invalid ccache"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_store_credentials */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t creds = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrInvalidCredentials, + ccErrBadCredentialsVersion, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_store_credentials + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_store_credentials(ccache, credentials); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + while (!err) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + if (compare_v5_creds_unions(credentials, creds->data) == 0) { + break; + } + cc_credentials_release(creds); + creds = NULL; + } + } + + if (err == ccIteratorEnd) { + check_if((creds != NULL), "stored credentials not found in ccache"); + err = ccNoError; + } + if (creds) { cc_credentials_release(creds); } + + #endif /* cc_ccache_store_credentials */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_remove_credentials(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_t creds_array[10]; + cc_credentials_t creds = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_string_t name = NULL; + unsigned int i; + + BEGIN_TEST("cc_ccache_remove_credentials"); + + #ifndef cc_ccache_remove_credentials + log_error("cc_ccache_remove_credentials is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // store 10 creds and retrieve their cc_credentials_t representations + for(i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + if (&creds_union) { release_v5_creds_union(&creds_union); } + } + if (err) { + log_error("failure to store creds_union in remove_creds test"); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + i = 0; + while (!err && i < 10) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + creds_array[i++] = creds; + creds = NULL; + } + } + if (err == ccIteratorEnd) { err = ccNoError; } + + // remove 10 valid creds + for (i = 0; !err && (i < 8); i++) { + check_once_cc_ccache_remove_credentials(ccache, creds_array[i], ccNoError, "10 ok creds"); + } + + // NULL param + check_once_cc_ccache_remove_credentials(ccache, NULL, ccErrBadParam, "NULL creds in param"); + + // non-existent creds (remove same one twice) + check_once_cc_ccache_remove_credentials(ccache, creds_array[0], ccErrInvalidCredentials, "removed same creds twice"); + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_remove_credentials(ccache, creds_array[8], ccErrInvalidCCache, "invalid ccache"); + } + + for(i = 0; i < 10; i++) { + if (creds_array[i]) { cc_credentials_release(creds_array[i]); } + } + + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_remove_credentials */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t creds = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrInvalidCredentials, + ccErrCredentialsNotFound, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_remove_credentials + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_remove_credentials(ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly removed + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + while (!err) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + if (compare_v5_creds_unions(in_creds->data, creds->data) == 0) { + break; + } + cc_credentials_release(creds); + creds = NULL; + } + } + + if (err == ccIteratorEnd) { + err = ccNoError; + } + else { + check_if((creds != NULL), "credentials not removed from ccache"); + } + if (creds) { cc_credentials_release(creds); } + + #endif /* cc_ccache_remove_credentials */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_new_credentials_iterator(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_iterator_t creds_iterator = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_new_credentials_iterator"); + + #ifndef cc_ccache_new_credentials_iterator + log_error("cc_ccache_new_credentials_iterator is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // valid params + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccNoError, "valid params"); + } + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + + // NULL out param + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, NULL, ccErrBadParam, "NULL out iterator param"); + } + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccErrInvalidCCache, "invalid ccache"); + } + + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_new_credentials_iterator */ + + END_TEST_AND_RETURN +} + + +cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrBadParam, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrInvalidCCache, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_new_credentials_iterator + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_new_credentials_iterator(ccache, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_ccache_new_credentials_iterator */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t this_time = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_change_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time == NULL) { + err = cc_ccache_get_change_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead + } else { + err = cc_ccache_get_change_time(ccache, &this_time); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if ((!err) && last_time) { + check_if(this_time <= *last_time, "change time didn't increase when expected"); + *last_time = this_time; + } + + #endif /* cc_ccache_get_change_time */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_change_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t dummy_ccache = NULL; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t credentials = NULL; + cc_time_t last_time = 0; + + BEGIN_TEST("cc_ccache_get_change_time"); + + #ifndef cc_ccache_get_change_time + log_error("cc_ccache_get_change_time is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create some ccaches (so that the one we keep around as 'ccache' is not default) + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (ccache) { + cc_ccache_release(ccache); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); + } + + // change it in all the ways it can change, checking after each + + // the ccache is created + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "new ccache (change time should be > 0)"); + } + + // the ccache is made default + if (!err) { + err = cc_ccache_set_default(ccache); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "non-default ccache became default"); + } + + // the ccache is made not-default + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "something@ELSE.COM", &dummy_ccache); + } + if (!err) { + err = cc_ccache_set_default(dummy_ccache); + } + if (dummy_ccache) { + cc_ccache_release(dummy_ccache); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "default ccache became non-default"); + } + + // try with bad params + + // NULL out param + if (!err) { + check_once_cc_ccache_get_change_time(ccache, NULL, ccErrBadParam, "NULL out param for time"); + } + + // store a credential + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "stored new credential"); + + if (!err) { + // change principal (fails with ccErrBadInternalMessage) + err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = ccNoError; + } + } + check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after changing a principle"); + + // remove a credential + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + if (!err) { + err = cc_credentials_iterator_next(creds_iterator, &credentials); + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (!err) { + err = cc_ccache_remove_credentials(ccache, credentials); + } + check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after removing a credential"); + + + // invalid ccache + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccErrInvalidCCache, "getting change time on destroyed ccache"); + } + + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_change_time */ + + END_TEST_AND_RETURN +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t this_time = 0; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrNeverDefault, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_last_default_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time == NULL) { + err = cc_ccache_get_last_default_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead + } else { + err = cc_ccache_get_last_default_time(ccache, &this_time); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && last_time) { + check_if(this_time > *last_time, "last default time isn't as expected"); + *last_time = this_time; + } + + #endif /* cc_ccache_get_last_default_time */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_last_default_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache_1 = NULL; + cc_ccache_t ccache_2 = NULL; + cc_time_t last_time_1 = 0; + cc_time_t last_time_2 = 0; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_get_last_default_time"); + + #ifndef cc_ccache_get_last_default_time + log_error("cc_ccache_get_last_default_time is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create 2 ccaches + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &ccache_1); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &ccache_2); + } + + if (!err) { + err = cc_ccache_get_change_time(ccache_1, &last_time_1); + } + + // since we destroyed all ccaches before creating these two, + // ccache_1 should be default and ccache_2 should never have been default + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 default at creation"); + check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccErrNeverDefault, "ccache_2 never default"); + } + + // make ccache_2 default and check each of their times again + if (!err) { + err = cc_ccache_set_default(ccache_2); + } + if (!err) { + err = cc_ccache_get_change_time(ccache_2, &last_time_2); + } + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 no longer default"); + check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccNoError, "ccache_2 newly default"); + } + + // NULL param + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, NULL, ccErrBadParam, "NULL out param"); + } + + // non-existent ccache + if (ccache_2) { + cc_ccache_release(ccache_2); + ccache_2 = NULL; + } + if (!err) { + err = cc_ccache_get_name(ccache_1, &name); + } + if (!err) { + err = cc_context_open_ccache(context, name->data, &ccache_2); + } + if (!err) { + cc_ccache_destroy(ccache_2); + ccache_2 = NULL; + } + + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccErrInvalidCCache, "destroyed ccache"); + } + + if (ccache_1) { cc_ccache_release(ccache_1); } + + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_last_default_time */ + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_move(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t source = NULL; + cc_ccache_t destination = NULL; + + cc_credentials_union creds_union; + unsigned int i = 0; + + BEGIN_TEST("cc_ccache_move"); + + #ifndef cc_ccache_move + log_error("cc_ccache_move is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create 2 ccaches + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &source); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &destination); + } + + // store credentials in each + for (i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "ONE.ORG"); + err = cc_ccache_store_credentials(source, &creds_union); + } + for (i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "TWO.ORG"); + err = cc_ccache_store_credentials(destination, &creds_union); + } + + // move source into destination + if (!err) { + check_once_cc_ccache_move(source, destination, ccNoError, "valid params"); + } + + // NULL param + if (!err) { + check_once_cc_ccache_move(destination, NULL, ccErrBadParam, "NULL destination param"); + } + + // non-existent ccache + if (!err) { + check_once_cc_ccache_move(destination, source, ccErrInvalidCCache, "recently moved source as destination param"); + } + + if (source) { cc_ccache_release(source); } + if (destination) { cc_ccache_release(destination); } + + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_move */ + + END_TEST_AND_RETURN + + +} + +cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_t dst_creds[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; + cc_credentials_t creds = NULL; + cc_credentials_iterator_t cred_iterator = NULL; + unsigned int i = 0; + + cc_string_t src_principal = NULL; + cc_string_t dst_principal = NULL; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_move + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (destination) { + // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) + if (!err) { + err = cc_ccache_new_credentials_iterator(destination, &cred_iterator); + } + while (!err && (i < 10)) { + err = cc_credentials_iterator_next(cred_iterator, &creds); + if (creds) { + dst_creds[i++] = creds; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (cred_iterator) { + cc_credentials_iterator_release(cred_iterator); + cred_iterator = NULL; + } + + // verify that destination's principal has changed to source's (strcmp) + if (!err) { + err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); + } + } + + + if (!err) { + err = cc_ccache_move(source, destination); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + + if (!err) { + // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) + i = 0; + while (dst_creds[i] && (i < 10)) { + err = cc_ccache_remove_credentials(destination, dst_creds[i]); + check_if(!(!err || err == ccErrCredentialsNotFound || ccErrInvalidCredentials), "credentials in destination not removed as promised"); + cc_credentials_release(dst_creds[i]); + i++; + } + err = ccNoError; + } + + // verify that destination's principal has changed to source's (strcmp) + if (!err) { + err = cc_ccache_get_principal(destination, cc_credentials_v5, &dst_principal); + } + if (!err) { + check_if(strcmp(src_principal->data, dst_principal->data), "destination principal not overwritten by source"); + } + + // verify that handles for source are no longer valid (get_change_time) + if (src_principal) { + cc_string_release(src_principal); + src_principal = NULL; + } + if (!err) { + err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); + check_if(err != ccErrInvalidCCache, "source ccache was not invalidated after move"); + } + + + if (cred_iterator) { cc_credentials_iterator_release(cred_iterator); } + if (src_principal) { cc_string_release(src_principal); } + if (dst_principal) { cc_string_release(dst_principal); } + + #endif /* cc_ccache_move */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_compare(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache_a = NULL; + cc_ccache_t ccache_b = NULL; + cc_uint32 equal = 0; + + BEGIN_TEST("cc_ccache_compare"); + + #ifndef cc_ccache_compare + log_error("cc_ccache_compare is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache_a); + } + if (!err) { + err = cc_context_open_default_ccache(context, &ccache_b); + } + + equal = 1; + check_once_cc_ccache_compare(ccache_a, ccache_a, &equal, ccNoError, "compare ccache with same pointer"); + equal = 1; + check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different handles to same ccache"); + + if (ccache_b) { + cc_ccache_release(ccache_b); + ccache_b = NULL; + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache_b); + } + equal = 0; + check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different ccaches"); + check_once_cc_ccache_compare(ccache_a, NULL, &equal, ccErrBadParam, "NULL compare_to ccache"); + check_once_cc_ccache_compare(ccache_a, ccache_b, NULL, ccErrBadParam, "NULL out param"); + + if (ccache_a) { cc_ccache_release(ccache_a); } + if (ccache_b) { cc_ccache_release(ccache_b); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_compare */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_uint32 actually_equal = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrServerUnavailable, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_compare + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (equal) { + actually_equal = *equal; + } + + err = cc_ccache_compare(ccache, compare_to, equal); + + if (!err && equal) { + if (actually_equal) { + check_if(actually_equal != *equal, "equal ccaches not considered equal"); + } + else { + check_if(actually_equal != *equal, "non-equal ccaches considered equal"); + } + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_ccache_compare */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_time_t time_offset = 0; + + BEGIN_TEST("cc_ccache_get_kdc_time_offset"); + + #ifndef cc_ccache_get_kdc_time_offset + log_error("cc_ccache_get_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + time_offset = 0; + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccErrTimeOffsetNotSet, "brand new ccache (offset not yet set)"); + + time_offset = 10; + if (!err) { + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, time_offset); + } + if (!err) { + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccNoError, "offset set for v5 but not v4"); + } + if (!err) { + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccErrTimeOffsetNotSet, "asking for v4 offset when only v5 is set"); + } + if (!err) { + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, time_offset); + } + if (!err) { + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccNoError, "asking for v4 offset when v4 and v5 are set"); + } + + + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL time_offset out param"); + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4_v5, &time_offset, ccErrBadCredentialsVersion, "v4_v5 creds_vers in param (invalid)"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t expected_offset; + + cc_int32 possible_return_values[7] = { + ccNoError, + ccErrTimeOffsetNotSet, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (time_offset) { + expected_offset = *time_offset; + } + + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, time_offset); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && time_offset) { + check_if(*time_offset != expected_offset, "kdc time offset doesn't match expected value"); + } + + #endif /* cc_ccache_get_kdc_time_offset */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_kdc_time_offset"); + + #ifndef cc_ccache_set_kdc_time_offset + log_error("cc_ccache_set_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0, ccNoError, "first time setting offset (v5)"); + check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0, ccNoError, "first time setting offset (v4)"); + + check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4_v5, 0, ccErrBadCredentialsVersion, "invalid creds_vers (v4_v5)"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_set_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t stored_offset = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_kdc_time_offset(ccache, credentials_version, time_offset); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); + } + + if (!err) { + check_if(time_offset != stored_offset, "kdc time offset doesn't match expected value"); + } + + #endif /* cc_ccache_set_kdc_time_offset */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_clear_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_clear_kdc_time_offset"); + + #ifndef cc_ccache_clear_kdc_time_offset + log_error("cc_ccache_clear_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing an offset that was never set (v5)"); + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing an offset that was never set (v4)"); + + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0); + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0); + + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing v5"); + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing v4"); + + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4_v5, ccErrBadCredentialsVersion, "bad in param creds vers (v4_v5)"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_clear_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t stored_offset = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_clear_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_clear_kdc_time_offset(ccache, credentials_version); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); + check_if(err != ccErrTimeOffsetNotSet, "time offset not cleared"); + } + + #endif /* cc_ccache_clear_kdc_time_offset */ + + return err; +} + + diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_ccache.h b/krb5-1-7/src/ccapi/test/test_ccapi_ccache.h new file mode 100644 index 000000000..ecb062197 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_ccache.h @@ -0,0 +1,49 @@ +#ifndef _TEST_CCAPI_CCACHE_H_ +#define _TEST_CCAPI_CCACHE_H_ + +#include "test_ccapi_globals.h" + +int check_cc_ccache_release(void); +cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_destroy(void); +cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_set_default(void); +cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_credentials_version(void); +cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_name(void); +cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_principal(void); +cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *expected_principal, cc_int32 expected_err, const char *description); +int check_cc_ccache_set_principal(void); +cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description); + +int check_cc_ccache_store_credentials(void); +cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description); +int check_cc_ccache_remove_credentials(void); +cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description); + +int check_cc_ccache_new_credentials_iterator(void); +cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description); + +int check_cc_ccache_get_change_time(void); +cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_last_default_time(void); +cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description); + +int check_cc_ccache_move(void); +cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description); + +int check_cc_ccache_compare(void); +cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description); + +int check_cc_ccache_get_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description); + +int check_cc_ccache_set_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description); + +int check_cc_ccache_clear_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_CCACHE_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_check.c b/krb5-1-7/src/ccapi/test/test_ccapi_check.c new file mode 100644 index 000000000..8352adfdc --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_check.c @@ -0,0 +1,37 @@ +#include "test_ccapi_check.h" + +int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...) { + if (expression) { + failure_count++; + // call with NULL format to get a generic error message + if (format == NULL) { + _log_error(file, line, expression_string); + } + // call with format and varargs for a more useful error message + else { + va_list ap; + va_start(ap, format); + _log_error_v(file, line, format, ap); + va_end(ap); + } + + if (current_test_activity) { + fprintf(stdout, " (%s)", current_test_activity); + } + } + + return (expression != 0); +} + +int array_contains_int(cc_int32 *array, int size, cc_int32 value) { + if (array != NULL && size > 0) { + int i = 0; + while (i < size && array[i] != value) { + i++; + } + if (i < size) { + return 1; + } + } + return 0; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_check.h b/krb5-1-7/src/ccapi/test/test_ccapi_check.h new file mode 100644 index 000000000..c05a5152e --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_check.h @@ -0,0 +1,43 @@ +#ifndef _TEST_CCAPI_CHECK_H_ +#define _TEST_CCAPI_CHECK_H_ + +#include +#include +#include "test_ccapi_log.h" +#include "test_ccapi_globals.h" + +int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...); + +#define check_int(a, b) \ + check_if(a != b, NULL) + +/* + * if expression evaluates to true, check_if increments the failure_count and prints: + * + * check_if(a!=a, NULL); + * ==> "/path/to/file:line: a!=a" + * + * check_if(a!=a, "This shouldn't be happening"); + * ==> "/path/to/file:line: This shouldn't be happening" + * + * check_if(a!=a, "This has happened %d times now", 3); + * ==> "/path/to/file:line: This has happened 3 times now" +*/ + +#define check_if(expression, format, ...) \ + _check_if(expression, __FILE__, __LINE__, #expression, format , ## __VA_ARGS__) + +#define check_if_not(expression, format, ...) \ + check_if(!(expression), format, ## __VA_ARGS__) + +// first check if err is what we were expecting to get back +// then check if err is even in the set of errors documented for the function +#define check_err(err, expected_err, possible_return_values) \ + do { \ + check_if(err != expected_err, "unexpected error %s (%d), expected %s (%d)", translate_ccapi_error(err), err, translate_ccapi_error(expected_err), expected_err); \ + check_if_not(array_contains_int(possible_return_values, possible_ret_val_count, err), "error not documented as a possible return value: %s (%d)", translate_ccapi_error(err), err); \ + } while( 0 ) + +int array_contains_int(cc_int32 *array, int size, cc_int32 value); + +#endif /* _TEST_CCAPI_CHECK_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_constants.c b/krb5-1-7/src/ccapi/test/test_ccapi_constants.c new file mode 100644 index 000000000..10d07f061 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_constants.c @@ -0,0 +1,66 @@ +#include "test_ccapi_constants.h" +#include "test_ccapi_globals.h" +#include "test_ccapi_check.h" + +int check_constants(void) { + BEGIN_TEST("constants"); + /* API versions */ + + check_int(ccapi_version_2, 2); + check_int(ccapi_version_3, 3); + check_int(ccapi_version_4, 4); + check_int(ccapi_version_5, 5); + check_int(ccapi_version_6, 6); + + /* Errors */ + + check_int(ccNoError , 0 ); // 0 + check_int(ccIteratorEnd , 201); // 201 + check_int(ccErrBadParam , 202); // 202 + check_int(ccErrNoMem , 203); // 203 + check_int(ccErrInvalidContext , 204); // 204 + check_int(ccErrInvalidCCache , 205); // 205 + check_int(ccErrInvalidString , 206); // 206 + check_int(ccErrInvalidCredentials , 207); // 207 + check_int(ccErrInvalidCCacheIterator , 208); // 208 + check_int(ccErrInvalidCredentialsIterator , 209); // 209 + check_int(ccErrInvalidLock , 210); // 210 + check_int(ccErrBadName , 211); // 211 + check_int(ccErrBadCredentialsVersion , 212); // 212 + check_int(ccErrBadAPIVersion , 213); // 213 + check_int(ccErrContextLocked , 214); // 214 + check_int(ccErrContextUnlocked , 215); // 215 + check_int(ccErrCCacheLocked , 216); // 216 + check_int(ccErrCCacheUnlocked , 217); // 217 + check_int(ccErrBadLockType , 218); // 218 + check_int(ccErrNeverDefault , 219); // 219 + check_int(ccErrCredentialsNotFound , 220); // 220 + check_int(ccErrCCacheNotFound , 221); // 221 + check_int(ccErrContextNotFound , 222); // 222 + check_int(ccErrServerUnavailable , 223); // 223 + check_int(ccErrServerInsecure , 224); // 224 + check_int(ccErrServerCantBecomeUID , 225); // 225 + check_int(ccErrTimeOffsetNotSet , 226); // 226 + check_int(ccErrBadInternalMessage , 227); // 227 + check_int(ccErrNotImplemented , 228); // 228 + + /* Credentials versions */ + + check_int(cc_credentials_v4, 1); + check_int(cc_credentials_v5, 2); + check_int(cc_credentials_v4_v5, (cc_credentials_v4 | cc_credentials_v5)); + + /* Lock types */ + + check_int(cc_lock_read, 0); + check_int(cc_lock_write, 1); + check_int(cc_lock_upgrade, 2); + check_int(cc_lock_downgrade, 3); + + /* Locking Modes */ + + check_int(cc_lock_noblock, 0); + check_int(cc_lock_block, 1); + + END_TEST_AND_RETURN +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_constants.h b/krb5-1-7/src/ccapi/test/test_ccapi_constants.h new file mode 100644 index 000000000..bc3f4f3b7 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_constants.h @@ -0,0 +1,6 @@ +#ifndef _TEST_CCAPI_CONSTANTS_H_ +#define _TEST_CCAPI_CONSTANTS_H_ + +int check_constants(void); + +#endif /* _TEST_CCAPI_CONSTANTS_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_context.c b/krb5-1-7/src/ccapi/test/test_ccapi_context.c new file mode 100644 index 000000000..51714539e --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_context.c @@ -0,0 +1,990 @@ +#include +#include "test_ccapi_context.h" +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +int check_cc_initialize(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + + BEGIN_TEST("cc_initialize"); + + // try every api_version + err = check_once_cc_initialize(&context, ccapi_version_2, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_2"); // err == CC_BAD_API_VERSION (9) would be imported by CredentialsCache2.h + err = check_once_cc_initialize(&context, ccapi_version_3, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_3"); // !err + err = check_once_cc_initialize(&context, ccapi_version_4, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_4"); // " + err = check_once_cc_initialize(&context, ccapi_version_5, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_5"); // " + err = check_once_cc_initialize(&context, ccapi_version_6, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_6"); // " + + // try bad api_version + err = check_once_cc_initialize(&context, INT_MAX, NULL, NULL, ccErrBadAPIVersion, NULL); // err == ccErrBadAPIVersion + + // try bad param + err = check_once_cc_initialize(NULL, ccapi_version_3, NULL, NULL, ccErrBadParam, NULL); // err == ccErrBadParam + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_context_t context; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrNoMem, + ccErrBadAPIVersion, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_initialize(out_context, in_version, out_supported_version, out_vendor); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (out_context) { context = *out_context; } + else { context = NULL; } + + // check output parameters + if (!err) { + check_if(context == NULL, NULL); + if (context) { + cc_context_release(context); + *out_context = NULL; + } + } else { + check_if(context != NULL, NULL); + } + + return err; +} + +int check_cc_context_release(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + + BEGIN_TEST("cc_context_release"); + + #ifndef cc_context_release + log_error("cc_context_release is not implemented yet"); + failure_count++; + #else + + // try with valid context + err = check_once_cc_context_release(&context, ccNoError, NULL); + + // try with NULL + //err = check_once_cc_context_release(NULL, ccErrInvalidContext); + /* calling with NULL context crashes, because this macro expands to + ((NULL) -> functions -> release (NULL)) which is dereferencing NULL which is bad. */ + + if (context) { cc_context_release(context); } + + #endif /* cc_context_release */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_context_t context = NULL; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidContext, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_release + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (out_context) { + err = cc_initialize(out_context, ccapi_version_3, NULL, NULL); + if (!err) { + context = *out_context; + } + } + + if (err != ccNoError) { + log_error("failure in cc_initialize, unable to perform check"); + return err; + } + else { + err = cc_context_release(context); + // check returned error + check_err(err, expected_err, possible_return_values); + } + + *out_context = NULL; + + #endif /* cc_context_release */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_get_change_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_time_t last_change_time = 0; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t credentials = NULL; + + BEGIN_TEST("cc_context_get_change_time"); + + #ifndef cc_context_get_change_time + log_error("cc_context_get_change_time is not implemented yet"); + failure_count++; + #else + + /* + * Make a context + * make sure the change time changes after: + * a ccache is created + * a ccache is destroyed + * a credential is stored + * a credential is removed + * a ccache principal is changed + * the default ccache is changed + * clean up memory + */ + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + + // try bad parameters first + err = check_once_cc_context_get_change_time(context, NULL, ccErrBadParam, "NULL param, should fail"); + + // make sure we have a default ccache + err = cc_context_open_default_ccache(context, &ccache); + if (err == ccErrCCacheNotFound) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_release(ccache); + } + // either the default ccache already existed or we just created it + // either way, the get_change_time should now give something > 0 + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "first-run, should be > 0"); + + // create a ccache + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after creating a new ccache"); + + // store a credential + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after storing a credential"); + + if (!err) { + // change principal (fails with ccErrBadInternalMessage) + err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = ccNoError; + } + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing a principle"); + + // remove a credential + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + if (!err) { + err = cc_credentials_iterator_next(creds_iterator, &credentials); + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (!err) { + err = cc_ccache_remove_credentials(ccache, credentials); + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after removing a credential"); + + if (!err) { + // change default ccache + err = cc_ccache_set_default(ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing default ccache"); + } + + if (ccache) { + // destroy a ccache + err = cc_ccache_destroy(ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after destroying a ccache"); + } + } + + if (context) { cc_context_release(context); } + + #endif /* cc_get_change_time */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_time_t last_change_time; + cc_time_t current_change_time = 0; + + cc_int32 possible_return_values[3] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_get_change_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (time != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_get_change_time(context, ¤t_change_time); + } else { + err = cc_context_get_change_time(context, NULL); + } + + check_err(err, expected_err, possible_return_values); + + if (!err) { + last_change_time = *time; + check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time); + *time = current_change_time; + } + + #endif /* cc_context_get_change_time */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_get_default_ccache_name(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_get_default_ccache_name"); + + #ifndef cc_context_get_default_ccache_name + log_error("cc_context_get_default_ccache_name is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try bad parameters first + err = check_once_cc_context_get_default_ccache_name(context, NULL, ccErrBadParam, NULL); + + // try with no default + err = destroy_all_ccaches(context); + err = cc_context_open_default_ccache(context, &ccache); + if (err != ccErrCCacheNotFound) { + log_error("didn't remove all ccaches"); + } + err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL); + + // try normally + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (ccache) { cc_ccache_release(ccache); } + err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL); + + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_get_default_ccache_name */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrNoMem, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_get_default_ccache_name + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (name != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_get_default_ccache_name(context, name); + } else { + err = cc_context_get_default_ccache_name(context, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + // not really anything else to check + + if (name && *name) { cc_string_release(*name); } + + #endif /* cc_context_get_default_ccache_name */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_open_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_open_ccache"); + + #ifndef cc_context_open_ccache + log_error("cc_context_open_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // make sure we have a default ccache + err = cc_context_open_default_ccache(context, &ccache); + if (err == ccErrCCacheNotFound) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try default ccache + err = cc_context_get_default_ccache_name(context, &name); + if (!err) { + err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_open_ccache(context, NULL, &ccache, ccErrBadParam, NULL); + err = check_once_cc_context_open_ccache(context, name->data, NULL, ccErrBadParam, NULL); + + // try a ccache that doesn't exist (create one and then destroy it) + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (!err) { + err = cc_ccache_destroy(ccache); + ccache = NULL; + } + + err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccErrCCacheNotFound, NULL); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_open_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_name = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, + ccErrInvalidContext, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_open_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_open_ccache(context, name, ccache); + } else { + err = cc_context_open_ccache(context, name, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + if (!err) { + err = cc_ccache_get_name(*ccache, &stored_name); + } + if (!err) { + check_if(strcmp(stored_name->data, name), NULL); + } + if (stored_name) { cc_string_release(stored_name); } + + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_open_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_open_default_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_context_open_default_ccache"); + + #ifndef cc_context_open_default_ccache + log_error("cc_context_open_default_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // make sure we have a default ccache + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + if (ccache) { cc_ccache_release(ccache); } + + // try default ccache + if (!err) { + err = check_once_cc_context_open_default_ccache(context, &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_open_default_ccache(context, NULL, ccErrBadParam, NULL); + + // try with no default ccache (destroy all ccaches first) + err = destroy_all_ccaches(context); + + err = check_once_cc_context_open_default_ccache(context, &ccache, ccErrCCacheNotFound, NULL); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_open_default_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t given_name = NULL; + cc_string_t default_name = NULL; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrInvalidContext, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_open_default_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_open_default_ccache(context, ccache); + } else { + err = cc_context_open_default_ccache(context, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure this ccache is the one we were looking to get back (compare name with cc_context_get_default_ccache_name) + err = cc_ccache_get_name(*ccache, &given_name); + err = cc_context_get_default_ccache_name(context, &default_name); + if (given_name && default_name) { + check_if(strcmp(given_name->data, default_name->data), "name of ccache returned by cc_context_open_default_ccache doesn't match name returned by cc_context_get_default_ccache_name"); + } + if (given_name) { cc_string_release(given_name); } + if (default_name) { cc_string_release(default_name); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_open_default_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_ccache"); + + #ifndef cc_context_create_ccache + log_error("cc_context_create_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making a ccache with a non-unique name (the existing default's name) + if (!err) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (ccache) { cc_ccache_release(ccache); } + if (!err) { + err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try making a ccache with a unique name (the now destroyed default's name) + if (ccache) { cc_ccache_destroy(ccache); } + if (!err) { + err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_create_ccache(context, NULL, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccErrBadParam, "NULL name"); // NULL name + err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers + err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_name = NULL; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_ccache(context, name, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure all of the ccache's info matches what we gave it + // name + err = cc_ccache_get_name(*ccache, &stored_name); + if (!err) { check_if(strcmp(stored_name->data, name), NULL); } + if (stored_name) { cc_string_release(stored_name); } + // cred_vers + // FIXME Documented function name of cc_ccache_get_credentials_version is a typo. + // FIXME Documented type of creds param the wrong signedness (should be unsigned) for cc_ccache_get_credentials_version, cc_context_create_ccache, cc_context_create_default_ccache, cc_context_create_new_ccache + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_destroy(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_default_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_default_ccache"); + + #ifndef cc_context_create_default_ccache + log_error("cc_context_create_default_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making the default when there are no existing ccaches + err = destroy_all_ccaches(context); + if (!err) { + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try making a new default when one already exists + if (!err) { + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_default_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, // how can this be possible when the name isn't a parameter? + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_default_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_default_ccache(context, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + if (ccache) { check_if(*ccache == NULL, NULL); } + // make sure all of the ccache's info matches what we gave it + // cred_vers + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_default_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_new_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_new_ccache"); + + #ifndef cc_context_create_new_ccache + log_error("cc_context_create_new_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making when there are no existing ccaches (should have name of default) + err = destroy_all_ccaches(context); + if (!err) { + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try making a new ccache when one already exists (should not have name of default) + if (!err) { + err = check_once_cc_context_create_new_ccache(context, 0, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try bad parameters + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_new_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t name = NULL; + cc_string_t stored_name = NULL; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, // how can this be possible when the name isn't a parameter? + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_new_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_new_ccache(context, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + if (ccache) { check_if(*ccache == NULL, NULL); } + // make sure all of the ccache's info matches what we gave it + if (!err) { + err = cc_context_get_default_ccache_name(context, &name); + } + if (!err) { + err = cc_ccache_get_name(*ccache, &stored_name); + } + if (!err) { + if (should_be_default) { + check_if(strcmp(stored_name->data, name->data), "new ccache does not have name of default"); + } + else { + check_if((strcmp(stored_name->data, name->data) == 0), "new cache has name of default"); + } + } + if (name) { cc_string_release(name); } + if (stored_name) { cc_string_release(stored_name); } + + // cred_vers + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_new_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_new_ccache_iterator(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + cc_ccache_iterator_t iterator = NULL; + + BEGIN_TEST("cc_context_new_ccache_iterator"); + + #ifndef cc_context_new_ccache_iterator + log_error("cc_context_new_ccache_iterator is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + // try making when there are no existing ccaches (shouldn't make a difference, but just in case) + check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when there are no existing ccaches"); + + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + // try making when at least one ccache already exists (just to cover all our bases) + check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when at least one ccache already exists"); + + // try bad parameters + check_once_cc_context_new_ccache_iterator(context, NULL, ccErrBadParam, "NULL param"); // NULL iterator + } + // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_new_ccache_iterator */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidContext, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_new_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_new_ccache_iterator(context, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // we'll do a comprehensive test of cc_ccache_iterator related functions later + + #endif /* cc_context_create_new_ccache */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_context_compare(void) { + cc_int32 err = 0; + cc_context_t context_a = NULL; + cc_context_t context_b = NULL; + cc_uint32 equal = 0; + + BEGIN_TEST("cc_context_compare"); + + #ifndef cc_context_compare + log_error("cc_context_compare is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context_a, ccapi_version_3, NULL, NULL); + if (!err) { + err = cc_initialize(&context_b, ccapi_version_3, NULL, NULL); + } + + check_once_cc_context_compare(context_a, context_a, &equal, ccNoError, "valid params, same contexts"); + check_once_cc_context_compare(context_a, context_b, &equal, ccNoError, "valid params, different contexts"); + check_once_cc_context_compare(context_a, NULL, &equal, ccErrBadParam, "NULL compare_to context"); + check_once_cc_context_compare(context_a, context_b, NULL, ccErrBadParam, "NULL out param"); + + if (context_a) { cc_context_release(context_a); } + if (context_b) { cc_context_release(context_b); } + + #endif /* cc_context_compare */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrServerUnavailable, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_compare + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_compare(context, compare_to, equal); + + if (!err) { + *equal = 0; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_context_compare */ + + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_context.h b/krb5-1-7/src/ccapi/test/test_ccapi_context.h new file mode 100644 index 000000000..2c3a4ab8f --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_context.h @@ -0,0 +1,32 @@ +#ifndef _TEST_CCAPI_CONTEXT_H_ +#define _TEST_CCAPI_CONTEXT_H_ + +#include "test_ccapi_globals.h" + +int check_cc_initialize(void); +cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description); +int check_cc_context_get_version(void); +cc_int32 check_once_cc_context_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description); +int check_cc_context_release(void); +cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description); +int check_cc_context_get_change_time(void); +cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description); +int check_cc_context_get_default_ccache_name(void); +cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description); +int check_cc_context_open_ccache(void); +cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_open_default_ccache(void); +cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_ccache(void); +cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_default_ccache(void); +cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_new_ccache(void); +cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_new_ccache_iterator(void); +cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description); + +int check_cc_context_compare(void); +cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_CONTEXT_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_globals.c b/krb5-1-7/src/ccapi/test/test_ccapi_globals.c new file mode 100644 index 000000000..f9aadbdda --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_globals.c @@ -0,0 +1,87 @@ +#include "test_ccapi_globals.h" + +/* GLOBALS */ +unsigned int total_failure_count = 0; +unsigned int failure_count = 0; + +const char *current_test_name; +const char *current_test_activity; + +const char * ccapi_error_strings[30] = { + + "ccNoError", /* 0 */ + "ccIteratorEnd", /* 201 */ + "ccErrBadParam", + "ccErrNoMem", + "ccErrInvalidContext", + "ccErrInvalidCCache", + + "ccErrInvalidString", /* 206 */ + "ccErrInvalidCredentials", + "ccErrInvalidCCacheIterator", + "ccErrInvalidCredentialsIterator", + "ccErrInvalidLock", + + "ccErrBadName", /* 211 */ + "ccErrBadCredentialsVersion", + "ccErrBadAPIVersion", + "ccErrContextLocked", + "ccErrContextUnlocked", + + "ccErrCCacheLocked", /* 216 */ + "ccErrCCacheUnlocked", + "ccErrBadLockType", + "ccErrNeverDefault", + "ccErrCredentialsNotFound", + + "ccErrCCacheNotFound", /* 221 */ + "ccErrContextNotFound", + "ccErrServerUnavailable", + "ccErrServerInsecure", + "ccErrServerCantBecomeUID", + + "ccErrTimeOffsetNotSet", /* 226 */ + "ccErrBadInternalMessage", + "ccErrNotImplemented", + +}; + +const char * ccapiv2_error_strings[24] = { + + "CC_NOERROR", + "CC_BADNAME", + "CC_NOTFOUND", + "CC_END", + "CC_IO", + "CC_WRITE", + "CC_NOMEM", + "CC_FORMAT", + "CC_LOCKED", + "CC_BAD_API_VERSION", + "CC_NO_EXIST", + "CC_NOT_SUPP", + "CC_BAD_PARM", + "CC_ERR_CACHE_ATTACH", + "CC_ERR_CACHE_RELEASE", + "CC_ERR_CACHE_FULL", + "CC_ERR_CRED_VERSION" + +}; + +const char *translate_ccapi_error(cc_int32 err) { + + if (err == 0) { + return ccapi_error_strings[0]; + } else + if (err >= 0 && err <= 16){ + return ccapiv2_error_strings[err]; + } else + if (err >= 201 && err <= 228){ + return ccapi_error_strings[err - 200]; + } + else { + return "\"Invalid or private CCAPI error\""; + } + + return ""; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_globals.h b/krb5-1-7/src/ccapi/test/test_ccapi_globals.h new file mode 100644 index 000000000..fb2d5dbbd --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_globals.h @@ -0,0 +1,57 @@ +#ifndef _TEST_CCAPI_GLOBALS_H_ +#define _TEST_CCAPI_GLOBALS_H_ + +#include // gets us TARGET_OS_MAC + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +#ifdef TARGET_OS_MAC +#include +#else +#include +#endif + +/* GLOBALS */ +extern unsigned int total_failure_count; +extern unsigned int failure_count; + +extern const char *current_test_name; +extern const char *current_test_activity; + +extern const char * ccapi_error_strings[30]; + +const char *translate_ccapi_error(cc_int32 err); + +#define T_CCAPI_INIT \ + do { \ + current_test_name = NULL; \ + current_test_activity = NULL; \ + } while( 0 ) + +#define BEGIN_TEST(name) \ + do { \ + current_test_name = name; \ + failure_count = 0; \ + test_header(current_test_name); \ + } while( 0 ) + +#define BEGIN_CHECK_ONCE(x) \ + do { \ + if (x) { \ + current_test_activity = x; \ + } \ + } while( 0 ) + +#define END_CHECK_ONCE \ + do { \ + current_test_activity = NULL; \ + } while( 0 ) + +#define END_TEST_AND_RETURN \ + test_footer(current_test_name, failure_count); \ + total_failure_count += failure_count; \ + return failure_count; + +#endif /* _TEST_CCAPI_GLOBALS_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_iterators.c b/krb5-1-7/src/ccapi/test/test_ccapi_iterators.c new file mode 100644 index 000000000..c3254fbb2 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_iterators.c @@ -0,0 +1,246 @@ +#include "test_ccapi_globals.h" +#include "test_ccapi_iterators.h" +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +// --------------------------------------------------------------------------- + +int check_cc_ccache_iterator_next(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_iterator_t iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_ccache_iterator_next"); + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // iterate with no ccaches + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 0, ccNoError, "iterating over an empty collection"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + // iterate with one ccache + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 1, ccNoError, "iterating over a collection of 1 ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches(context); + } + for(i = 0; !err && (i < 1000); i++) + { + if (i%100 == 0) fprintf(stdout, "."); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + } + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 1000, ccNoError, "iterating over a collection of 1000 ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + + if (ccache) { cc_ccache_release(ccache); } + if (iterator) { cc_ccache_iterator_release(iterator); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + +// BEGIN_CHECK_ONCE(description); + + cc_int32 possible_return_values[6] = { + ccNoError, + ccIteratorEnd, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidCCacheIterator, + ccErrCCacheNotFound, + }; + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + cc_ccache_t ccache = NULL; + cc_uint32 actual_count = 0; + + while (!err) { + err = cc_ccache_iterator_next(iterator, &ccache); + if (ccache) { + actual_count++; + cc_ccache_release(ccache); + ccache = NULL; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + +// END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_credentials_iterator_next(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_credentials_iterator_next"); + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // iterate with no creds + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 0, ccNoError, "iterating over an empty ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // iterate with one cred + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 1, ccNoError, "iterating over a ccache with 1 cred"); + if (iterator) { + cc_credentials_iterator_release(iterator); + iterator = NULL; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // iterate with several creds + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + for(i = 0; !err && (i < 1000); i++) { + if (i%100 == 0) fprintf(stdout, "."); + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 1000, ccNoError, "iterating over a ccache with 1000 creds"); + + if (ccache) { cc_ccache_release(ccache); } + if (iterator) { cc_credentials_iterator_release(iterator); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_t creds = NULL; + cc_uint32 actual_count = 0; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccIteratorEnd, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidCredentialsIterator, + }; + + BEGIN_CHECK_ONCE(description); + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + while (!err) { + err = cc_credentials_iterator_next(iterator, &creds); + if (creds) { + actual_count++; + cc_credentials_release(creds); + creds = NULL; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_iterators.h b/krb5-1-7/src/ccapi/test/test_ccapi_iterators.h new file mode 100644 index 000000000..7308c7c49 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_iterators.h @@ -0,0 +1,12 @@ +#ifndef _TEST_CCAPI_ITERATORS_H_ +#define _TEST_CCAPI_ITERATORS_H_ + +#include "test_ccapi_globals.h" + +int check_cc_ccache_iterator_next(void); +cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description); + +int check_cc_credentials_iterator_next(void); +cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_ITERATORS_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_log.c b/krb5-1-7/src/ccapi/test/test_ccapi_log.c new file mode 100644 index 000000000..348d55cdc --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_log.c @@ -0,0 +1,45 @@ +#ifndef _TEST_CCAPI_LOG_C_ +#define _TEST_CCAPI_LOG_C_ + +#include "test_ccapi_log.h" + +void _log_error_v(const char *file, int line, const char *format, va_list ap) +{ + fprintf(stdout, "\n\t%s:%d: ", file, line); + if (!format) { + fprintf(stdout, "An unknown error occurred"); + } else { + vfprintf(stdout, format, ap); + } + fflush(stdout); +} + +void _log_error(const char *file, int line, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + _log_error_v(file, line, format, ap); + va_end(ap); +} + +void test_header(const char *msg) { + if (msg != NULL) { + fprintf(stdout, "\nChecking %s... ", msg); + fflush(stdout); + } +} + +void test_footer(const char *msg, int err) { + if (msg != NULL) { + if (!err) { + fprintf(stdout, "OK\n"); + } + else { + fprintf(stdout, "\n*** %d failure%s in %s ***\n", err, (err == 1) ? "" : "s", msg); + } + } +} + + + +#endif /* _TEST_CCAPI_LOG_C_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_log.h b/krb5-1-7/src/ccapi/test/test_ccapi_log.h new file mode 100644 index 000000000..6305c1845 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_log.h @@ -0,0 +1,20 @@ +#ifndef _TEST_CCAPI_LOG_H_ +#define _TEST_CCAPI_LOG_H_ + +#include +#include +#include "test_ccapi_globals.h" + +#define log_error(format, ...) \ + _log_error(__FILE__, __LINE__, format , ## __VA_ARGS__) + +void _log_error_v(const char *file, int line, const char *format, va_list ap); +void _log_error(const char *file, int line, const char *format, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__ ((__format__ (__printf__, 3, 4))) +#endif +; +void test_header(const char *msg); +void test_footer(const char *msg, int err); + +#endif /* _TEST_CCAPI_LOG_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_util.c b/krb5-1-7/src/ccapi/test/test_ccapi_util.c new file mode 100644 index 000000000..1f66c991b --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_util.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include + +#include "k5-platform.h" /* pull in asprintf decl/defn */ +#include "test_ccapi_util.h" + + +// --------------------------------------------------------------------------- + +cc_int32 destroy_all_ccaches(cc_context_t context) { + cc_int32 err = ccNoError; + cc_ccache_t ccache = NULL; + + while (!err) { + err = cc_context_open_default_ccache(context, &ccache); + if (!err) { + err = cc_ccache_destroy(ccache); + } + } + if (err == ccErrCCacheNotFound) { + err = ccNoError; + } + else { + log_error("cc_context_open_default_ccache or cc_ccache_destroy failed with %s (%d)", translate_ccapi_error(err), err); + } + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 new_v5_creds_union (cc_credentials_union *out_union, const char *realm) +{ + cc_int32 err = ccNoError; + cc_credentials_union *cred_union = NULL; + cc_credentials_v5_t *v5creds = NULL; + static int num_runs = 1; + char *client = NULL; + char *server = NULL; + + if (!out_union) { err = ccErrBadParam; } + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (!v5creds) { + err = ccErrNoMem; + } + } + + if (!err) { + asprintf(&client, "client@%s", realm); + asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm); + if (!client || !server) { + err = ccErrNoMem; + } + } + + if (!err) { + v5creds->client = client; + v5creds->server = server; + v5creds->keyblock.type = 1; + v5creds->keyblock.length = 0; + v5creds->keyblock.data = NULL; + v5creds->authtime = time (NULL); + v5creds->starttime = time (NULL); + v5creds->endtime = time(NULL) + 1000; + v5creds->renew_till = time(NULL) + 10000; + v5creds->is_skey = 0; + v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL; + v5creds->addresses = NULL; + v5creds->ticket.type = 0; + v5creds->ticket.length = 0; + v5creds->ticket.data = NULL; + v5creds->second_ticket.type = 0; + v5creds->second_ticket.length = 0; + v5creds->second_ticket.data = NULL; + v5creds->authdata = NULL; + } + + + if (!err) { + cred_union = malloc (sizeof (*cred_union)); + if (cred_union) { + cred_union->version = cc_credentials_v5; + cred_union->credentials.credentials_v5 = v5creds; + } else { + err = ccErrNoMem; + } + } + if (!err) { + *out_union = *cred_union; + cred_union = NULL; + } + + return err; +} + + +// --------------------------------------------------------------------------- + +void release_v5_creds_union(cc_credentials_union *creds_union) { + cc_credentials_v5_t *v5creds = NULL; + + if (creds_union) { + if (creds_union->credentials.credentials_v5) { + v5creds = creds_union->credentials.credentials_v5; + if (v5creds->client) { free(v5creds->client); } + if (v5creds->server) { free(v5creds->server); } + if (v5creds->keyblock.data) { free(v5creds->keyblock.data); } + if (v5creds->ticket.data) { free(v5creds->ticket.data); } + if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); } + free(v5creds); + } + //free(creds_union); + } +} + + +// --------------------------------------------------------------------------- + +// return zero when both unions are considered equal, non-zero when not + +int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b) { + int retval = -1; + + if (a && + b && + (a->version == cc_credentials_v5) && + (a->version == b->version) && + (strcmp(a->credentials.credentials_v5->client, b->credentials.credentials_v5->client) == 0) && + (strcmp(a->credentials.credentials_v5->server, b->credentials.credentials_v5->server) == 0)) + { + retval = 0; + } + + return retval; +} diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_util.h b/krb5-1-7/src/ccapi/test/test_ccapi_util.h new file mode 100644 index 000000000..4e98e257e --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_util.h @@ -0,0 +1,13 @@ +#ifndef _TEST_CCAPI_UTIL_H_ +#define _TEST_CCAPI_UTIL_H_ + +#include "test_ccapi_globals.h" +#include "test_ccapi_log.h" + +cc_int32 destroy_all_ccaches(cc_context_t context); + +cc_int32 new_v5_creds_union(cc_credentials_union *out_union, const char *realm); +void release_v5_creds_union(cc_credentials_union *creds_union); +int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b); + +#endif /* _TEST_CCAPI_UTIL_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_v2.c b/krb5-1-7/src/ccapi/test/test_ccapi_v2.c new file mode 100644 index 000000000..054d216e6 --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_v2.c @@ -0,0 +1,1840 @@ +#include +#include "k5-platform.h" /* pull in asprintf decl/defn */ +#include "test_ccapi_v2.h" +#include +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +// --------------------------------------------------------------------------- + +static cc_result destroy_all_ccaches_v2(apiCB *context) { + cc_result err = CC_NOERROR; + infoNC **info = NULL; + int i = 0; + + err = cc_get_NC_info(context, &info); + + for (i = 0; !err && info[i]; i++) { + ccache_p *ccache = NULL; + + err = cc_open(context, info[i]->name, info[i]->vers, 0, &ccache); + + if (!err) { cc_destroy(context, &ccache); } + } + + if (info) { cc_free_NC_info(context, &info); } + + if (err) { + log_error("cc_get_NC_info or cc_open failed with %s (%d)", translate_ccapi_error(err), err); + } + + return err; +} + +// --------------------------------------------------------------------------- +// return zero when both unions are considered equal, non-zero when not + +static int compare_v5_creds_unions_compat(const cred_union *a, const cred_union *b) { + int retval = -1; + + if (a && b && a->cred_type == b->cred_type) { + if (a->cred_type == CC_CRED_V5) { + if (!strcmp(a->cred.pV5Cred->client, b->cred.pV5Cred->client) && + !strcmp(a->cred.pV5Cred->server, b->cred.pV5Cred->server) && + a->cred.pV5Cred->starttime == b->cred.pV5Cred->starttime) { + retval = 0; + } + } else if (a->cred_type == CC_CRED_V4) { + if (!strcmp (a->cred.pV4Cred->principal, + b->cred.pV4Cred->principal) && + !strcmp (a->cred.pV4Cred->principal_instance, + b->cred.pV4Cred->principal_instance) && + !strcmp (a->cred.pV4Cred->service, + b->cred.pV4Cred->service) && + !strcmp (a->cred.pV4Cred->service_instance, + b->cred.pV4Cred->service_instance) && + !strcmp (a->cred.pV4Cred->realm, + b->cred.pV4Cred->realm) && + a->cred.pV4Cred->issue_date == b->cred.pV4Cred->issue_date) { + retval = 0; + } + } + } + + return retval; +} + +// --------------------------------------------------------------------------- + +static cc_result new_v5_creds_union_compat (cred_union *out_union, const char *realm) +{ + cc_result err = CC_NOERROR; + cred_union *creds_union = NULL; + cc_credentials_v5_compat *v5creds = NULL; + static int num_runs = 1; + char *client = NULL; + char *server = NULL; + + if (!out_union) { err = CC_BAD_PARM; } + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (!v5creds) { + err = CC_NOMEM; + } + } + + if (!err) { + asprintf(&client, "client@%s", realm); + asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm); + if (!client || !server) { + err = CC_NOMEM; + } + } + + if (!err) { + v5creds->client = client; + v5creds->server = server; + v5creds->keyblock.type = 1; + v5creds->keyblock.length = 0; + v5creds->keyblock.data = NULL; + v5creds->authtime = time (NULL); + v5creds->starttime = time (NULL); + v5creds->endtime = time(NULL) + 1000; + v5creds->renew_till = time(NULL) + 10000; + v5creds->is_skey = 0; + v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL; + v5creds->addresses = NULL; + v5creds->ticket.type = 0; + v5creds->ticket.length = 0; + v5creds->ticket.data = NULL; + v5creds->second_ticket.type = 0; + v5creds->second_ticket.length = 0; + v5creds->second_ticket.data = NULL; + v5creds->authdata = NULL; + } + + + if (!err) { + creds_union = malloc (sizeof (*creds_union)); + if (creds_union) { + creds_union->cred_type = CC_CRED_V5; + creds_union->cred.pV5Cred = v5creds; + } else { + err = CC_NOMEM; + } + } + if (!err) { + *out_union = *creds_union; + creds_union = NULL; + } + + return err; +} + +// --------------------------------------------------------------------------- + +static void release_v5_creds_union_compat(cred_union *creds_union) { + cc_credentials_v5_compat *v5creds = NULL; + + if (creds_union) { + if (creds_union->cred.pV5Cred) { + v5creds = creds_union->cred.pV5Cred; + if (v5creds->client) { free(v5creds->client); } + if (v5creds->server) { free(v5creds->server); } + if (v5creds->keyblock.data) { free(v5creds->keyblock.data); } + if (v5creds->ticket.data) { free(v5creds->ticket.data); } + if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); } + free(v5creds); + } + } +} + +// --------------------------------------------------------------------------- + +int check_cc_shutdown(void) { + cc_result err = 0; + apiCB *context = NULL; + + BEGIN_TEST("cc_shutdown"); + + // try with valid context + err = check_once_cc_shutdown(&context, CC_NOERROR, NULL); + + // try with NULL + err = check_once_cc_shutdown(NULL, CC_BAD_PARM, NULL); + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description) { + cc_result err = 0; + apiCB *context = NULL; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (out_context) { + err = cc_initialize(out_context, ccapi_version_2, NULL, NULL); + if (!err) { + context = *out_context; + } else { + log_error("failure in cc_initialize, unable to perform check"); + return err; + } + } + + if (!err) { + err = cc_shutdown(&context); + // check returned error + check_err(err, expected_err, possible_return_values); + + } + + if (out_context) { + *out_context = NULL; + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_change_time(void) { + cc_result err = 0; + apiCB *context = NULL; + cc_time_t last_change_time = 0; + ccache_p *ccache = NULL; + cred_union creds_union; + + BEGIN_TEST("cc_get_change_time"); + + /* + * Make a context + * make sure the change time changes after: + * a ccache is created + * a ccache is destroyed + * a credential is stored + * a credential is removed + * a ccache principal is changed + * clean up memory + */ + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + + // try bad parameters first + err = check_once_cc_get_change_time(context, NULL, CC_BAD_PARM, "NULL param, should fail"); + + // get_change_time should always give something > 0 + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "first-run, should be > 0"); + + // create a ccache + err = cc_create(context, "TEST_CCACHE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (err) { + log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after creating a new ccache"); + + if (!err) { + // change principal + err = cc_set_principal(context, ccache, CC_CRED_V5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after changing a principle"); + + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + // store a credential + if (!err) { + err = cc_store(context, ccache, creds_union); + if (err) { + log_error("failed to store a credential - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after storing a credential"); + + // remove a credential + if (!err) { + err = cc_remove_cred(context, ccache, creds_union); + if (err) { + log_error("failed to remove a credential - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after removing a credential"); + + release_v5_creds_union_compat(&creds_union); + + if (ccache) { + // destroy a ccache + err = cc_destroy(context, &ccache); + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after destroying a ccache"); + } + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *last_time, cc_result expected_err, const char *description) { + cc_result err = 0; + cc_time_t last_change_time; + cc_time_t current_change_time = 0; + + cc_result possible_return_values[3] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_get_change_time(context, ¤t_change_time); + } else { + err = cc_get_change_time(context, NULL); + } + + check_err(err, expected_err, possible_return_values); + + if (!err) { + last_change_time = *last_time; + check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time); + *last_time = current_change_time; + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_open(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_OPEN_CCACHE"; + + BEGIN_TEST("cc_open"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + // create a ccache + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (err) { + log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + } + if (!err) { + err = cc_close(context, &ccache); + ccache = NULL; + } + + // try default ccache + if (!err) { + err = check_once_cc_open(context, name, CC_CRED_V5, &ccache, CC_NOERROR, NULL); + } + + // check version + if (!err) { + err = check_once_cc_open(context, name, CC_CRED_V4, &ccache, CC_ERR_CRED_VERSION, NULL); + } + // try bad parameters + err = check_once_cc_open(context, NULL, CC_CRED_V5, &ccache, CC_BAD_PARM, NULL); + err = check_once_cc_open(context, name, CC_CRED_V5, NULL, CC_BAD_PARM, NULL); + err = check_once_cc_open(context, name, CC_CRED_UNKNOWN, &ccache, CC_ERR_CRED_VERSION, NULL); + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description) { + cc_result err = 0; + char *stored_name = NULL; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + CC_NOMEM, + CC_ERR_CRED_VERSION + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_open(context, name, version, 0, ccache); + } else { + err = cc_open(context, name, version, 0, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + if (!err) { + err = cc_get_name(context, *ccache, &stored_name); + } + if (!err) { + check_if(strcmp(stored_name, name), NULL); + } + if (stored_name) { cc_free_name(context, &stored_name); } + + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_create(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_CREATE"; + + BEGIN_TEST("cc_create"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + if (!err) { + err = cc_destroy (context, &ccache); + } else { + err = CC_NOERROR; /* ccache does not exist */ + } + } + // try making a ccache with a unique name (the now destroyed cache's name) + if (!err) { + err = check_once_cc_create(context, name, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_NOERROR, NULL); + } + + // try making a ccache with a non-unique name (the existing cache's name) + if (!err) { + err = check_once_cc_create(context, name, CC_CRED_V5, "foo/baz@BAR.ORG", &ccache, CC_NOERROR, NULL); + } + + // try bad parameters + err = check_once_cc_create(context, NULL, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_BAD_PARM, "NULL name"); // NULL name + err = check_once_cc_create(context, "name", CC_CRED_MAX, "foo@BAR.ORG", &ccache, CC_ERR_CRED_VERSION, "invalid creds_vers"); // invalid creds_vers + err = check_once_cc_create(context, "name", CC_CRED_V5, NULL, &ccache, CC_BAD_PARM, "NULL principal"); // NULL principal + err = check_once_cc_create(context, "name", CC_CRED_V5, "foo@BAR.ORG", NULL, CC_BAD_PARM, "NULL ccache"); // NULL ccache + } + + if (ccache) { cc_destroy(context, &ccache); } + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description) { + cc_result err = 0; + char *stored_name = NULL; + char *stored_principal = NULL; + cc_int32 stored_creds_vers = 0; + + cc_result possible_return_values[6] = { + CC_NOERROR, + CC_BADNAME, + CC_BAD_PARM, + CC_NO_EXIST, + CC_NOMEM, + CC_ERR_CRED_VERSION, + }; + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_create(context, name, principal, cred_vers, 0, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure all of the ccache's info matches what we gave it + // name + err = cc_get_name(context, *ccache, &stored_name); + if (!err) { check_if(strcmp(stored_name, name), NULL); } + if (stored_name) { cc_free_name(context, &stored_name); } + // cred_vers + err = cc_get_cred_version(context, *ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_get_principal(context, *ccache, &stored_principal); + if (!err) { check_if(strcmp(stored_principal, principal), NULL); } + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + if (ccache && *ccache) { + cc_destroy(context, ccache); + *ccache = NULL; + } + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_close(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_CLOSE"; + + BEGIN_TEST("cc_close"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + if (!err) { + check_once_cc_close(context, ccache, CC_NOERROR, NULL); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM + }; + + char *name = NULL; + + err = cc_get_name(context, ccache, &name); + err = cc_close(context, &ccache); + ccache = NULL; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + } + check_if(err == CC_NO_EXIST, "released ccache was actually destroyed instead"); + check_if(err != CC_NOERROR, "released ccache cannot be opened"); + + if (ccache) { cc_destroy(context, &ccache); } + if (name) { cc_free_name(context, &name); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_destroy(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_DESTROY"; + + BEGIN_TEST("cc_destroy"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + if (!err) { + check_once_cc_destroy(context, ccache, CC_NOERROR, NULL); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM, + }; + + char *name = NULL; + + BEGIN_CHECK_ONCE(description); + +#ifdef cc_ccache_destroy + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_get_name(context, ccache, &name); + err = cc_destroy(context, &ccache); + ccache = NULL; + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + } + check_if(err != CC_NO_EXIST, "destroyed ccache was actually released instead"); + + if (ccache) { cc_destroy(context, &ccache); } + if (name) { cc_free_name(context, &name); } + +#endif /* cc_ccache_destroy */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_cred_version(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_GET_CRED_VERSION_V5"; + + BEGIN_TEST("cc_get_cred_version"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + // try one created with v5 creds + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_cred_version(context, ccache, CC_CRED_V5, CC_NOERROR, "v5 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + err = CC_NOERROR; + + // try one created with v4 creds + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V4, 0, &ccache); + } + if (!err) { + check_once_cc_get_cred_version(context, ccache, CC_CRED_V4, CC_NOERROR, "v4 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[3] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + cc_int32 stored_cred_vers = 0; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_get_cred_version(context, ccache, &stored_cred_vers); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(stored_cred_vers != expected_cred_vers, NULL); + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_name(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + + BEGIN_TEST("cc_get_name"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // try with unique ccache (which happens to be default) + if (!err) { + err = cc_create(context, "0", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_name(context, ccache, "0", CC_NOERROR, "unique ccache (which happens to be default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // try with unique ccache (which is not default) + if (!err) { + err = cc_context_create_ccache(context, "1", CC_CRED_V5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_get_name(context, ccache, "1", CC_NOERROR, "unique ccache (which is not default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_get_name(context, ccache, NULL, CC_BAD_PARM, "NULL param"); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_NOMEM, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + char *stored_name = NULL; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_name == NULL) { // we want to try with a NULL param + err = cc_get_name(context, ccache, NULL); + } + else { + err = cc_get_name(context, ccache, &stored_name); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_name, expected_name), NULL); + } + + if (stored_name) { cc_free_name(context, &stored_name); } + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_get_principal(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5"; + char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4"; + + BEGIN_TEST("cc_get_principal"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // try with krb5 principal + if (!err) { + err = cc_create(context, name_v5, "foo/BAR@BAZ.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_principal(context, ccache, "foo/BAR@BAZ.ORG", CC_NOERROR, "trying to get krb5 princ for krb5 ccache"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // try with krb4 principal + if (!err) { + err = cc_create(context, name_v4, "foo.BAR@BAZ.ORG", CC_CRED_V4, 0, &ccache); + } + if (!err) { + check_once_cc_get_principal(context, ccache, "foo.BAR@BAZ.ORG", CC_NOERROR, "trying to get krb4 princ for krb4 ccache"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_get_principal(context, ccache, NULL, CC_BAD_PARM, "passed null out param"); + } + + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_principal(apiCB *context, + ccache_p *ccache, + const char *expected_principal, + cc_int32 expected_err, + const char *description) { + cc_result err = CC_NOERROR; + char *stored_principal = NULL; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_NOMEM, + CC_NO_EXIST, + CC_BAD_PARM + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_principal == NULL) { // we want to try with a NULL param + err = cc_get_principal(context, ccache, NULL); + } + else { + err = cc_get_principal(context, ccache, &stored_principal); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_principal, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal); + } + + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_set_principal(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5"; + char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4"; + + BEGIN_TEST("cc_set_principal"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // bad params + if (!err) { + err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_set_principal(context, ccache, CC_CRED_MAX, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "CC_CRED_MAX (not allowed)"); + check_once_cc_set_principal(context, ccache, CC_CRED_V5, NULL, CC_BAD_PARM, "NULL principal"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + // empty ccache + + // replace v5 ccache's principal + if (!err) { + err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_NOERROR, "replace v5 only ccache's principal (empty ccache)"); + check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v5 principal with v4"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + // replace v4 ccache's principal + if (!err) { + err = cc_create(context, name_v4, "foo@BAZ.ORG", CC_CRED_V4, 0, &ccache); + } + if (!err) { + check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_NOERROR, "replace v4 only ccache's principal (empty ccache)"); + check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v4 principal with v5"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + char *stored_principal = NULL; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_NOMEM, + CC_NO_EXIST, + CC_ERR_CRED_VERSION, + CC_BAD_PARM + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_set_principal(context, ccache, cred_vers, (char *) in_principal); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_get_principal(context, ccache, &stored_principal); + } + + // compare stored with input + if (!err) { + check_if(strcmp(stored_principal, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal); + } + + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_store(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_p *dup_ccache = NULL; + cred_union creds_union; + char *name = NULL; + + BEGIN_TEST("cc_store"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_STORE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // cred with matching version and realm + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + check_once_cc_store(context, ccache, creds_union, CC_NOERROR, "ok creds"); + release_v5_creds_union_compat(&creds_union); + } + } + + // invalid creds + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + if (creds_union.cred.pV5Cred->client) { + free(creds_union.cred.pV5Cred->client); + creds_union.cred.pV5Cred->client = NULL; + } + check_once_cc_store(context, ccache, creds_union, CC_BAD_PARM, "invalid creds (NULL client string)"); + + release_v5_creds_union_compat(&creds_union); + } + } + + // bad creds version + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + creds_union.cred_type = CC_CRED_MAX; + check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "CC_CRED_MAX (invalid) into a ccache with only v5 princ"); + creds_union.cred_type = CC_CRED_V4; + check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "v4 creds into a v5 ccache"); + creds_union.cred_type = CC_CRED_V5; + + release_v5_creds_union_compat(&creds_union); + } + } + + // non-existent ccache + if (ccache) { + err = cc_get_name(context, ccache, &name); + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + if (name) { cc_free_name(context, &name); } + if (dup_ccache) { cc_destroy(context, &dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + check_once_cc_store(context, ccache, creds_union, CC_NO_EXIST, "invalid ccache"); + + release_v5_creds_union_compat(&creds_union); + } + } + + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + ccache_cit *iterator = NULL; + int found = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_ERR_CACHE_FULL, + CC_ERR_CRED_VERSION, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_store(context, ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + while (!err && !found) { + cred_union *creds = NULL; + + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (!err) { + found = !compare_v5_creds_unions_compat(&in_creds, creds); + } + + if (creds) { cc_free_creds(context, &creds); } + } + + if (err == CC_END) { + check_if(found, "stored credentials not found in ccache"); + err = CC_NOERROR; + } + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_remove_cred(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + cred_union *creds_array[10]; + ccache_cit *iterator = NULL; + char *name = NULL; + unsigned int i; + + BEGIN_TEST("cc_remove_cred"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_REMOVE_CRED", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // store 10 creds and retrieve their cc_credentials_t representations + for(i = 0; !err && (i < 10); i++) { + cred_union creds; + + new_v5_creds_union_compat(&creds, "BAR.ORG"); + err = cc_store(context, ccache, creds); + if (err) { + log_error("failure to store creds_union in remove_creds test"); + } + release_v5_creds_union_compat(&creds); + } + + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + + for (i = 0; !err && i < 10; i++) { + creds_array[i] = NULL; + err = cc_seq_fetch_creds_next(context, &creds_array[i], iterator); + } + if (err == CC_END) { err = CC_NOERROR; } + + // remove 10 valid creds + for (i = 0; !err && (i < 10); i++) { + check_once_cc_remove_cred(context, ccache, *creds_array[i], CC_NOERROR, "10 ok creds"); + } + + // non-existent creds (remove same one twice) + check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NOTFOUND, "removed same creds twice"); + + // non-existent ccache + if (ccache) { + ccache_p *dup_ccache = NULL; + + err = cc_get_name(context, ccache, &name); + + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + + if (!err) { + err = cc_destroy(context, &dup_ccache); + check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NO_EXIST, "invalid ccache"); + } + + if (name) { cc_free_name(context, &name); } + } + + for(i = 0; i < 10 && creds_array[i]; i++) { + cc_free_creds(context, &creds_array[i]); + } + + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); iterator = NULL; } + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + ccache_cit *iterator = NULL; + int found = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_ERR_CRED_VERSION, + CC_NOTFOUND, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_remove_cred(context, ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + + while (!err && !found) { + cred_union *creds = NULL; + + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (!err) { + found = !compare_v5_creds_unions_compat(&in_creds, creds); + } + + if (creds) { cc_free_creds(context, &creds); } + } + + if (err == CC_END) { + check_if(found, "credentials not removed from ccache"); + err = CC_NOERROR; + } + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_NCs_begin(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_cit *iterator = NULL; + + BEGIN_TEST("cc_seq_fetch_NCs_begin"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + err = destroy_all_ccaches_v2(context); + } + if (!err) { + // try making when there are no existing ccaches (shouldn't make a difference, but just in case) + check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when there are no existing ccaches"); + + err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + // try making when at least one ccache already exists (just to cover all our bases) + check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when at least one ccache already exists"); + + // try bad parameters + check_once_cc_seq_fetch_NCs_begin(context, NULL, CC_BAD_PARM, "NULL param"); // NULL iterator + } + // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite + + if (ccache ) { cc_close(context, &ccache); } + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_seq_fetch_NCs_begin(context, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // we'll do a comprehensive test of cc_ccache_iterator related functions later + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_NCs_next(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_cit *iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_seq_fetch_NCs_next"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no ccaches + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 0, CC_NOERROR, "iterating over an empty collection"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + // iterate with one ccache + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 1, CC_NOERROR, "iterating over a collection of 1 ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches_v2(context); + } + for(i = 0; !err && (i < 1000); i++) + { + char *name = NULL; + + if (i%100 == 0) fprintf(stdout, "."); + asprintf (&name, "TEST_CC_SEQ_FETCH_NCS_NEXT_%d", i); + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + free (name); + } + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + + if (ccache) { cc_close(context, &ccache); } + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_END, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + ccache_p *ccache = NULL; + cc_uint32 actual_count = 0; + + BEGIN_CHECK_ONCE(description); + + while (!err) { + err = cc_seq_fetch_NCs_next(context, &ccache, iterator); + if (ccache) { + actual_count++; + cc_close(context, &ccache); + ccache = NULL; + } + } + if (err == CC_END) { + err = CC_NOERROR; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_NC_info(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + unsigned int i; + + BEGIN_TEST("cc_get_NC_info"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no ccaches + check_once_cc_get_NC_info(context, "", "", CC_CRED_MAX, 0, CC_NOERROR, "iterating over an empty collection"); + + // iterate with one ccache + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1, CC_NOERROR, "iterating over a collection of 1 ccache"); + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches_v2(context); + } + for(i = 0; !err && (i < 1000); i++) + { + char *name = NULL; + + if (i%100 == 0) fprintf(stdout, "."); + asprintf (&name, "TEST_CC_GET_NC_INFO_%d", i); + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + free (name); + } + check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache"); + + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_NC_info(apiCB *context, + const char *expected_name_prefix, + const char *expected_principal, + cc_int32 expected_version, + cc_uint32 expected_count, + cc_result expected_err, + const char *description) { + cc_result err = CC_NOERROR; + infoNC **info = NULL; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + cc_uint32 actual_count = 0; + + BEGIN_CHECK_ONCE(description); + + err = cc_get_NC_info(context, &info); + + for (actual_count = 0; !err && info[actual_count]; actual_count++) { + check_if(strncmp(info[actual_count]->name, expected_name_prefix, strlen(expected_name_prefix)), "got incorrect ccache name"); + check_if(strcmp(info[actual_count]->principal, expected_principal), "got incorrect principal name"); + check_if(info[actual_count]->vers != expected_version, "got incorrect cred version"); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "NC info didn't list all ccaches"); + + if (info) { cc_free_NC_info (context, &info); } + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_creds_begin(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_p *dup_ccache = NULL; + ccache_cit *creds_iterator = NULL; + char *name = NULL; + + BEGIN_TEST("cc_seq_fetch_creds_begin"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // valid params + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NOERROR, "valid params"); + } + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + + // NULL out param + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, NULL, CC_BAD_PARM, "NULL out iterator param"); + } + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + + // non-existent ccache + if (ccache) { + err = cc_get_name(context, ccache, &name); + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + if (name) { cc_free_name(context, &name); } + if (dup_ccache) { cc_destroy(context, &dup_ccache); } + } + + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NO_EXIST, "invalid ccache"); + } + + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_seq_fetch_creds_begin(context, ccache, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_creds_next(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + cred_union creds_union; + ccache_cit *iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_seq_fetch_creds_next"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no creds + if (!err) { + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 0, CC_NOERROR, "iterating over an empty ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // iterate with one cred + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + err = cc_store(context, ccache, creds_union); + release_v5_creds_union_compat(&creds_union); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 1, CC_NOERROR, "iterating over a ccache with 1 cred"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // iterate with several creds + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + for(i = 0; !err && (i < 1000); i++) { + if (i%100 == 0) fprintf(stdout, "."); + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + err = cc_store(context, ccache, creds_union); + release_v5_creds_union_compat(&creds_union); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 1000, CC_NOERROR, "iterating over a ccache with 1000 creds"); + + if (ccache) { cc_close(context, &ccache); } + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + cred_union *creds = NULL; + cc_uint32 actual_count = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_END, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + while (!err) { + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (creds) { + actual_count++; + cc_free_creds(context, &creds); + creds = NULL; + } + } + if (err == CC_END) { + err = CC_NOERROR; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} + diff --git a/krb5-1-7/src/ccapi/test/test_ccapi_v2.h b/krb5-1-7/src/ccapi/test/test_ccapi_v2.h new file mode 100644 index 000000000..55abdffde --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_ccapi_v2.h @@ -0,0 +1,73 @@ +#ifndef _TEST_CCAPI_V2_H_ +#define _TEST_CCAPI_V2_H_ + +#include "test_ccapi_globals.h" +#ifdef TARGET_OS_MAC +#include +#else +#include +#endif + + +int check_cc_shutdown(void); +cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description); + +int check_cc_get_change_time(void); +cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *time, cc_result expected_err, const char *description); + +int check_cc_open(void); +cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description); + +int check_cc_create(void); +cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description); + +int check_cc_close(void); +cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description); + +int check_cc_destroy(void); +cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description); + +int check_cc_get_cred_version(void); +cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description); + +int check_cc_get_name(void); +cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description); + +int check_cc_get_principal(void); +cc_result check_once_cc_get_principal(apiCB *context, + ccache_p *ccache, + const char *expected_principal, + cc_int32 expected_err, + const char *description); + +int check_cc_set_principal(void); +cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description); + +int check_cc_store(void); +cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description); + +int check_cc_remove_cred(void); +cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description); + +int check_cc_seq_fetch_NCs_begin(void); +cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description); + +int check_cc_seq_fetch_NCs_next(void); +cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description); + +int check_cc_get_NC_info(void); +cc_result check_once_cc_get_NC_info(apiCB *context, + const char *expected_name, + const char *expected_principal, + cc_int32 expected_version, + cc_uint32 expected_count, + cc_result expected_err, + const char *description); + +int check_cc_seq_fetch_creds_begin(void); +cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description); + +int check_cc_seq_fetch_creds_next(void); +cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description); + +#endif /* _TEST_CCAPI_V2_H_ */ diff --git a/krb5-1-7/src/ccapi/test/test_constants.c b/krb5-1-7/src/ccapi/test/test_constants.c new file mode 100644 index 000000000..367baac4c --- /dev/null +++ b/krb5-1-7/src/ccapi/test/test_constants.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_constants(); + return err; +} diff --git a/krb5-1-7/src/clients/Makefile.in b/krb5-1-7/src/clients/Makefile.in new file mode 100644 index 000000000..3a6af6ecb --- /dev/null +++ b/krb5-1-7/src/clients/Makefile.in @@ -0,0 +1,55 @@ +thisconfigdir=.. +myfulldir=clients +mydir=clients +BUILDTOP=$(REL).. + +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-7/src/clients/deps b/krb5-1-7/src/clients/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/clients/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/clients/kcpytkt/Makefile.in b/krb5-1-7/src/clients/kcpytkt/Makefile.in new file mode 100644 index 000000000..882b93d72 --- /dev/null +++ b/krb5-1-7/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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kcpytkt.o $(KRB5_BASE_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-7/src/clients/kcpytkt/kcpytkt.M b/krb5-1-7/src/clients/kcpytkt/kcpytkt.M new file mode 100644 index 000000000..11ed93929 --- /dev/null +++ b/krb5-1-7/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-7/src/clients/kcpytkt/kcpytkt.c b/krb5-1-7/src/clients/kcpytkt/kcpytkt.c new file mode 100644 index 000000000..8efddb413 --- /dev/null +++ b/krb5-1-7/src/clients/kcpytkt/kcpytkt.c @@ -0,0 +1,182 @@ + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +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-7/src/clients/kdeltkt/Makefile.in b/krb5-1-7/src/clients/kdeltkt/Makefile.in new file mode 100644 index 000000000..fece6d894 --- /dev/null +++ b/krb5-1-7/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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kdeltkt.o $(KRB5_BASE_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-7/src/clients/kdeltkt/kdeltkt.M b/krb5-1-7/src/clients/kdeltkt/kdeltkt.M new file mode 100644 index 000000000..a9f369418 --- /dev/null +++ b/krb5-1-7/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-7/src/clients/kdeltkt/kdeltkt.c b/krb5-1-7/src/clients/kdeltkt/kdeltkt.c new file mode 100644 index 000000000..832a07075 --- /dev/null +++ b/krb5-1-7/src/clients/kdeltkt/kdeltkt.c @@ -0,0 +1,174 @@ + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +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-7/src/clients/kdestroy/Makefile.in b/krb5-1-7/src/clients/kdestroy/Makefile.in new file mode 100644 index 000000000..00b8f5863 --- /dev/null +++ b/krb5-1-7/src/clients/kdestroy/Makefile.in @@ -0,0 +1,41 @@ +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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kdestroy.o $(KRB5_BASE_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 diff --git a/krb5-1-7/src/clients/kdestroy/deps b/krb5-1-7/src/clients/kdestroy/deps new file mode 100644 index 000000000..e0ec42e6a --- /dev/null +++ b/krb5-1-7/src/clients/kdestroy/deps @@ -0,0 +1,6 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdestroy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \ + kdestroy.c diff --git a/krb5-1-7/src/clients/kdestroy/kdestroy.M b/krb5-1-7/src/clients/kdestroy/kdestroy.M new file mode 100644 index 000000000..ada2ae3dc --- /dev/null +++ b/krb5-1-7/src/clients/kdestroy/kdestroy.M @@ -0,0 +1,81 @@ +.\" 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\-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. +.SH OPTIONS +.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. +.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). +.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-7/src/clients/kdestroy/kdestroy.c b/krb5-1-7/src/clients/kdestroy/kdestroy.c new file mode 100644 index 000000000..3f2f32682 --- /dev/null +++ b/krb5-1-7/src/clients/kdestroy/kdestroy.c @@ -0,0 +1,150 @@ +/* + * 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 +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#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; + + +static void usage() +{ +#define KRB_AVAIL_STRING(x) ((x)?"available":"not available") + + fprintf(stderr, "Usage: %s [-q] [-c cache_name]\n", progname); + 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; + int errflg = 0; + int quiet = 0; + + progname = GET_PROGNAME(argv[0]); + + 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': + fprintf(stderr, "Kerberos 4 is no longer supported\n"); + exit(3); + break; + case '5': + break; + case '?': + default: + errflg++; + break; + } + } + + if (optind != argc) + errflg++; + + if (errflg) { + usage(); + } + + retval = krb5_init_context(&kcontext); + if (retval) { + com_err(progname, retval, "while initializing krb5"); + exit(1); + } + + if (cache_name) { + 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; + } + } + return errflg; +} diff --git a/krb5-1-7/src/clients/kinit/Makefile.in b/krb5-1-7/src/clients/kinit/Makefile.in new file mode 100644 index 000000000..a2b928f34 --- /dev/null +++ b/krb5-1-7/src/clients/kinit/Makefile.in @@ -0,0 +1,44 @@ +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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kinit.o $(KRB5_BASE_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 diff --git a/krb5-1-7/src/clients/kinit/deps b/krb5-1-7/src/clients/kinit/deps new file mode 100644 index 000000000..144fe22a1 --- /dev/null +++ b/krb5-1-7/src/clients/kinit/deps @@ -0,0 +1,7 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kinit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + kinit.c diff --git a/krb5-1-7/src/clients/kinit/kinit.M b/krb5-1-7/src/clients/kinit/kinit.M new file mode 100644 index 000000000..5b85772ac --- /dev/null +++ b/krb5-1-7/src/clients/kinit/kinit.M @@ -0,0 +1,201 @@ +.\" 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\-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\-C\fP] +[\fB\-E\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\-T\fP \fIarmor_ccache\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 . +.SH OPTIONS +.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. +.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. +.TP +.B \-f +request forwardable tickets. +.TP +.B \-F +do not request forwardable tickets. +.TP +.B \-p +request proxiable tickets. +.TP +.B \-P +do not request proxiable tickets. +.TP +.B \-a +request tickets with the local address[es]. +.TP +.B \-A +request address-less tickets. +.TP +.B \-C +requests canonicalization of the principal name. +.TP +.B \-E +treats the principal name as an enterprise name. +.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. +.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. +.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. +.TP +\fB\-T\fP \fIarmor_ccache\fP +Specifies the name of a credential cache that already contains a +ticket. This ccache will be used to armor the request. Ideally, an +attacker should have to attack both the armor ticket and the key of +the principal. +.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 . +.TP +\fB\-S\fP \fIservice_name\fP +specify an alternate service name to use when +getting initial tickets. +.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. +.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 +/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-7/src/clients/kinit/kinit.c b/krb5-1-7/src/clients/kinit/kinit.c new file mode 100644 index 000000000..3f31824b0 --- /dev/null +++ b/krb5-1-7/src/clients/kinit/kinit.c @@ -0,0 +1,742 @@ +/* + * clients/kinit/kinit.c + * + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5-platform.h" /* for asprintf */ +#include +#include +#include +#include +#include +#include + +#ifdef GETOPT_LONG +#include +#else +#ifdef HAVE_UNISTD_H +#include +#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 +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; + +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 *armor_ccache; + + action_type action; + + int num_pa_opts; + krb5_gic_opt_pa_data *pa_opts; + + int canonicalize; + int enterprise; +}; + +struct k5_data +{ + krb5_context ctx; + krb5_ccache cc; + krb5_principal me; + char* name; +}; + +#ifdef GETOPT_LONG +/* if struct[2] == NULL, then long_getopt acts as if the short flag + struct[3] was specified. If struct[2] != NULL, then struct[3] is + stored in *(struct[2]), the array index which was specified is + stored in *index, and long_getopt() returns 0. */ + +struct option long_options[] = { + { "noforwardable", 0, NULL, 'F' }, + { "noproxiable", 0, NULL, 'P' }, + { "addresses", 0, NULL, 'a'}, + { "forwardable", 0, NULL, 'f' }, + { "proxiable", 0, NULL, 'p' }, + { "noaddresses", 0, NULL, 'A' }, + { "canonicalize", 0, NULL, 'C' }, + { "enterprise", 0, NULL, 'E' }, + { 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() +{ +#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_LONG_CANONICALIZE " | --canonicalize" +#define USAGE_LONG_ENTERPRISE " | --enterprise" +#define USAGE_BREAK_LONG USAGE_BREAK +#else +#define USAGE_LONG_FORWARDABLE "" +#define USAGE_LONG_PROXIABLE "" +#define USAGE_LONG_ADDRESSES "" +#define USAGE_LONG_CANONICALIZE "" +#define USAGE_LONG_ENTERPRISE "" +#define USAGE_BREAK_LONG "" +#endif + + fprintf(stderr, "Usage: %s [-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_LONG + "[-C" USAGE_LONG_CANONICALIZE "] " + USAGE_BREAK + "[-E" USAGE_LONG_ENTERPRISE "] " + USAGE_BREAK + "[-v] [-R] " + "[-k [-t keytab_file]] " + "[-c cachename] " + USAGE_BREAK + "[-S service_name] [-T ticket_armor_cache]" + USAGE_BREAK + "[-X [=]] [principal]" + "\n\n", + progname); + + fprintf(stderr, " options:"); + fprintf(stderr, "\t-V verbose\n"); + fprintf(stderr, "\t-l lifetime\n"); + fprintf(stderr, "\t-s start time\n"); + fprintf(stderr, "\t-r renewable lifetime\n"); + fprintf(stderr, "\t-f forwardable\n"); + fprintf(stderr, "\t-F not forwardable\n"); + fprintf(stderr, "\t-p proxiable\n"); + fprintf(stderr, "\t-P not proxiable\n"); + fprintf(stderr, "\t-a include addresses\n"); + fprintf(stderr, "\t-A do not include addresses\n"); + fprintf(stderr, "\t-v validate\n"); + fprintf(stderr, "\t-R renew\n"); + fprintf(stderr, "\t-C canonicalize\n"); + fprintf(stderr, "\t-E client is enterprise principal name\n"); + fprintf(stderr, "\t-k use keytab\n"); + fprintf(stderr, "\t-t filename of keytab to use\n"); + fprintf(stderr, "\t-c Kerberos 5 cache name\n"); + fprintf(stderr, "\t-S service\n"); + fprintf(stderr, "\t-T armor credential cache\n"); + fprintf(stderr, "\t-X [=]\n"); + 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) + int argc; + char **argv; + struct k_opts* opts; +{ + krb5_error_code code; + int errflg = 0; + int i; + + while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:T:RS:vX:CE")) + != -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 'T': + if (opts->armor_ccache) { + fprintf(stderr, "Only one armor_ccache\n"); + errflg++; + } else opts->armor_ccache = 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; + case 'C': + opts->canonicalize = 1; + break; + case 'E': + opts->enterprise = 1; + break; + case '4': + fprintf(stderr, "Kerberos 4 is no longer supported\n"); + exit(3); + break; + case '5': + 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++; + } + + if (errflg) { + usage(); + } + + opts->principal_name = (optind == argc-1) ? argv[optind] : 0; + return opts->principal_name; +} + +static int +k5_begin(opts, k5) + struct k_opts* opts; + struct k5_data* k5; +{ + krb5_error_code code = 0; + int flags = opts->enterprise ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 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_flags(k5->ctx, opts->principal_name, + flags, &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_flags(k5->ctx, name, + flags, &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; + + 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 krb5_error_code +KRB5_CALLCONV +kinit_prompter( + krb5_context ctx, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[] + ) +{ + krb5_error_code rc = + krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts); + return rc; +} + +static int +k5_kinit(opts, k5) + struct k_opts* opts; + struct k5_data* k5; +{ + 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; + + memset(&my_creds, 0, sizeof(my_creds)); + + code = krb5_get_init_creds_opt_alloc(k5->ctx, &options); + if (code) + goto cleanup; + + /* + 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->canonicalize) + krb5_get_init_creds_opt_set_canonicalize(options, 1); + 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->armor_ccache) + krb5_get_init_creds_opt_set_fast_ccache_name(k5->ctx, options, opts->armor_ccache); + + + 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 (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; + } + + code = krb5_cc_initialize(k5->ctx, k5->cc, + opts->canonicalize ? my_creds.client : 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; +} + +int +main(argc, argv) + int argc; + char **argv; +{ + struct k_opts opts; + struct k5_data k5; + int authed_k5 = 0; + + progname = GET_PROGNAME(argv[0]); + + /* 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); + + memset(&opts, 0, sizeof(opts)); + opts.action = INIT_PW; + + memset(&k5, 0, sizeof(k5)); + + set_com_err_hook (extended_com_err_fn); + + parse_options(argc, argv, &opts); + + if (k5_begin(&opts, &k5)) + authed_k5 = k5_kinit(&opts, &k5); + + if (authed_k5 && opts.verbose) + fprintf(stderr, "Authenticated to Kerberos v5\n"); + + k5_end(&k5); + + if (!authed_k5) + exit(1); + return 0; +} diff --git a/krb5-1-7/src/clients/klist/Makefile.in b/krb5-1-7/src/clients/klist/Makefile.in new file mode 100644 index 000000000..56e9b399c --- /dev/null +++ b/krb5-1-7/src/clients/klist/Makefile.in @@ -0,0 +1,42 @@ +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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ klist.o $(KRB5_BASE_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 + diff --git a/krb5-1-7/src/clients/klist/deps b/krb5-1-7/src/clients/klist/deps new file mode 100644 index 000000000..6f211b15f --- /dev/null +++ b/krb5-1-7/src/clients/klist/deps @@ -0,0 +1,8 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)klist.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.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 klist.c diff --git a/krb5-1-7/src/clients/klist/klist.M b/krb5-1-7/src/clients/klist/klist.M new file mode 100644 index 000000000..b3603fd5f --- /dev/null +++ b/krb5-1-7/src/clients/klist/klist.M @@ -0,0 +1,131 @@ +.\" 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\-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. +.SH OPTIONS +.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. +.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 +/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-7/src/clients/klist/klist.c b/krb5-1-7/src/clients/klist/klist.c new file mode 100644 index 000000000..c20aa9801 --- /dev/null +++ b/krb5-1-7/src/clients/klist/klist.c @@ -0,0 +1,671 @@ +/* + * 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 +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +/* Need definition of INET6 before network headers, for IRIX. */ +#if defined(HAVE_ARPA_INET_H) +#include +#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 +#include +#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, print_version = 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); + +#define DEFAULT 0 +#define CCACHE 1 +#define KEYTAB 2 + +static void usage() +{ +#define KRB_AVAIL_STRING(x) ((x)?"available":"not available") + + fprintf(stderr, "Usage: %s [-e] [-V] [[-c] [-f] [-s] [-a [-n]]] %s", + progname, "[-k [-t] [-K]] [name]\n"); + 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, "\t-V shows the Kerberos version and exits\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; + + progname = GET_PROGNAME(argv[0]); + + name = NULL; + mode = DEFAULT; + /* V=version so v can be used for verbose later if desired. */ + while ((c = getopt(argc, argv, "fetKsnack45V")) != -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': + fprintf(stderr, "Kerberos 4 is no longer supported\n"); + exit(3); + break; + case '5': + break; + case 'V': + print_version = 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(); + } + + if (print_version) { + printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + + name = (optind == argc-1) ? argv[optind] : 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; + } + + { + 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); + } + + 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 */ + snprintf(buf, sizeof(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 +#include +#include "autoconf.h" + +#ifndef _WIN32 +#include +#endif + +#include + +#define P1 "Enter new password" +#define P2 "Enter it again" + +#ifdef HAVE_PWD_H +#include + +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-7/src/clients/kpasswd/ksetpwd.c b/krb5-1-7/src/clients/kpasswd/ksetpwd.c new file mode 100644 index 000000000..45f782f08 --- /dev/null +++ b/krb5-1-7/src/clients/kpasswd/ksetpwd.c @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include +#include + +#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, (char *) 0 ); + else + kres = krb5_parse_name( kcontext, user, &kme ); + if( kres ) + goto fail; + krb5_unparse_name( kcontext, kme, &pName ); + if( cachename ) + { + if (asprintf(&pCacheName, "%s%s", cachename, pName) < 0) + { + kres = KRB5_CC_NOMEM; + goto fail; + } + 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-7/src/clients/ksu/Makefile.in b/krb5-1-7/src/clients/ksu/Makefile.in new file mode 100644 index 000000000..e91909857 --- /dev/null +++ b/krb5-1-7/src/clients/ksu/Makefile.in @@ -0,0 +1,43 @@ +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 diff --git a/krb5-1-7/src/clients/ksu/authorization.c b/krb5-1-7/src/clients/ksu/authorization.c new file mode 100644 index 000000000..0c90d2713 --- /dev/null +++ b/krb5-1-7/src/clients/ksu/authorization.c @@ -0,0 +1,721 @@ +/* + * 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 * 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, '/')){ + asprintf(&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 + asprintf(&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){ + asprintf(&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 */ + asprintf(&err,"Error: bad path %s in CMD_PATH for %s must start with '/' \n",tc, KRB5_USERS_NAME ); + *out_err = err; + return FALSE; + } + + tmp_fcmd[i] = xasprintf("%s/%s", tc, fcmd); + + 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; + struct k5buf buf; + + while(fcmd_arr[i]){ + if (!stat (fcmd_arr[i], &st_temp )){ + *cmd_out = xstrdup(fcmd_arr[i]); + retbool = TRUE; + break; + } + i++; + } + + if (retbool == FALSE ){ + krb5int_buf_init_dynamic(&buf); + krb5int_buf_add(&buf, "Error: not found -> "); + for(j= 0; j < i; j ++) + krb5int_buf_add_fmt(&buf, " %s ", fcmd_arr[j]); + krb5int_buf_add(&buf, "\n"); + *err_out = krb5int_buf_data(&buf); + if (*err_out == NULL) { + perror(prog_name); + exit(1); + } + } + + + 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; +{ + const char *sep; + int r1, r2; + + sep = ((strlen(pw_dir) == 1) && (*pw_dir == '/')) ? "" : "/"; + r1 = snprintf(k5login_path, sizeof(k5login_path), "%s%s%s", + pw_dir, sep, KRB5_LOGIN_NAME); + r2 = snprintf(k5users_path, sizeof(k5users_path), "%s%s%s", + pw_dir, sep, KRB5_USERS_NAME); + if (SNPRINTF_OVERFLOW(r1, sizeof(k5login_path)) || + SNPRINTF_OVERFLOW(r2, sizeof(k5users_path))) { + fprintf (stderr, + "home directory name `%s' too long, can't search for .k5login\n", + pw_dir); + exit (1); + } +} diff --git a/krb5-1-7/src/clients/ksu/ccache.c b/krb5-1-7/src/clients/ksu/ccache.c new file mode 100644 index 000000000..8fd11a3c8 --- /dev/null +++ b/krb5-1-7/src/clients/ksu/ccache.c @@ -0,0 +1,818 @@ +/* + * 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 +#include + +/****************************************************************** +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 ENOMEM; + } + + + 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 ENOMEM; + } + } + } + + } + + 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, result; + char ** buf_out; + struct stat st_temp; + int count = 0, chunk_count = 1; + + /* no account => no access */ + + if ((pwd = getpwnam(luser)) == NULL) { + return 0; + } + result = snprintf(pbuf, sizeof(pbuf), "%s/.k5login", pwd->pw_dir); + if (SNPRINTF_OVERFLOW(result, sizeof(pbuf))) { + fprintf (stderr, "home directory path for %s too long\n", luser); + exit (1); + } + + 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 ENOMEM; + + if (!(buf_out = (char **) malloc( CHUNK * sizeof(char *)))) return ENOMEM; + + 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 ENOMEM; + } + } + + /* 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 ENOMEM; + } + + 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-7/src/clients/ksu/deps b/krb5-1-7/src/clients/ksu/deps new file mode 100644 index 000000000..f1a8c1fae --- /dev/null +++ b/krb5-1-7/src/clients/ksu/deps @@ -0,0 +1,67 @@ +# +# Generated makefile dependencies follow. +# +$(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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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 \ + 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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 \ + 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 ksu.h xmalloc.c +$(OUTPRE)setenv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + setenv.c diff --git a/krb5-1-7/src/clients/ksu/heuristic.c b/krb5-1-7/src/clients/ksu/heuristic.c new file mode 100644 index 000000000..80482bebb --- /dev/null +++ b/krb5-1-7/src/clients/ksu/heuristic.c @@ -0,0 +1,765 @@ +/* + * 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 +#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 ENOMEM; + + 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 ENOMEM; + } + } + + + 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 ENOMEM; + + 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 ENOMEM; + + 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 (data_eq(*krb5_princ_realm(context, *client), + *krb5_princ_realm(context, temp_client))) { + + 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 || !data_eq(*p1, *p2)) { + 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-7/src/clients/ksu/krb_auth_su.c b/krb5-1-7/src/clients/ksu/krb_auth_su.c new file mode 100644 index 000000000..45e84d805 --- /dev/null +++ b/krb5-1-7/src/clients/ksu/krb_auth_su.c @@ -0,0 +1,464 @@ +/* + * 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" + + +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_verify_init_creds_opt vfy_opts; + 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 getting 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); + } + + krb5_verify_init_creds_opt_init(&vfy_opts); + krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1); + retval = krb5_verify_init_creds(context, out_creds, server, NULL /*keytab*/, + NULL /*output ccache*/, + &vfy_opts); + 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_verify_init_creds_opt vfy_opts; + 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) ; + + } + krb5_verify_init_creds_opt_init(&vfy_opts); + krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1); + retval = krb5_verify_init_creds(context, &tgt, server, NULL /*keytab*/, + NULL /*output ccache*/, + &vfy_opts); + if (retval){ + com_err(prog_name, retval, "while verifing ticket for server"); + return (FALSE); + } + + return TRUE; +} + + + +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]; + int result; + + *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; + + result = snprintf(prompt, sizeof(prompt), "Kerberos password for %s: ", + client_name); + if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) { + fprintf (stderr, + "principal name %s too long for internal buffer space\n", + client_name); + return FALSE; + } + + 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 (data_eq(*krb5_princ_realm(context, *client), + *krb5_princ_realm(context, temp_client))) { + + 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 (data_eq(*p1, *p2)) { + + 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-7/src/clients/ksu/ksu.M b/krb5-1-7/src/clients/ksu/ksu.M new file mode 100644 index 000000000..aeceaad30 --- /dev/null +++ b/krb5-1-7/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_. +The target cache name is automatically +set to krb5cc_.(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-7/src/clients/ksu/ksu.h b/krb5-1-7/src/clients/ksu/ksu.h new file mode 100644 index 000000000..76ed7032d --- /dev/null +++ b/krb5-1-7/src/clients/ksu/ksu.h @@ -0,0 +1,255 @@ +/* + * 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 +#include "com_err.h" +#include +#include +#include +#include +#include +#include +/* or 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 *); +extern char *xasprintf (const char *format, ...); + +#ifndef HAVE_UNSETENV +void unsetenv (char *); +#endif diff --git a/krb5-1-7/src/clients/ksu/main.c b/krb5-1-7/src/clients/ksu/main.c new file mode 100644 index 000000000..0aba56933 --- /dev/null +++ b/krb5-1-7/src/clients/ksu/main.c @@ -0,0 +1,998 @@ +/* + * 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 +#include +#include +#include + +/* 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 { + snprintf(cc_target_tag, KRB5_SEC_BUFFSIZE, "%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 + 5]; + int result; + + buf[0] = 0; + if ((p = ttyname(STDERR_FILENO))) { + result = snprintf(buf, sizeof(buf), " on %s", p); + if (SNPRINTF_OVERFLOW(result, sizeof(buf))) { + fprintf (stderr, "terminal name %s too long\n", p); + exit (1); + } + } + return (buf); +} + + +static int set_env_var(name, value) + char *name; + char *value; +{ + char * env_var_buf; + + asprintf(&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 ENOMEM; + } + + 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-7/src/clients/ksu/setenv.c b/krb5-1-7/src/clients/ksu/setenv.c new file mode 100644 index 000000000..056a478e5 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#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-7/src/clients/ksu/xmalloc.c b/krb5-1-7/src/clients/ksu/xmalloc.c new file mode 100644 index 000000000..44bdca16d --- /dev/null +++ b/krb5-1-7/src/clients/ksu/xmalloc.c @@ -0,0 +1,84 @@ +/* + * 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" +#include +#include "k5-platform.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; +} + +char *xasprintf (const char *format, ...) +{ + char *out; + va_list args; + + va_start (args, format); + if (vasprintf(&out, format, args) < 0) { + perror (prog_name); + exit (1); + } + va_end(args); + return out; +} diff --git a/krb5-1-7/src/clients/kvno/Makefile.in b/krb5-1-7/src/clients/kvno/Makefile.in new file mode 100644 index 000000000..23841c0f6 --- /dev/null +++ b/krb5-1-7/src/clients/kvno/Makefile.in @@ -0,0 +1,42 @@ +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 $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kvno.o $(KRB5_BASE_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 diff --git a/krb5-1-7/src/clients/kvno/deps b/krb5-1-7/src/clients/kvno/deps new file mode 100644 index 000000000..60f4595a8 --- /dev/null +++ b/krb5-1-7/src/clients/kvno/deps @@ -0,0 +1,6 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kvno.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \ + kvno.c diff --git a/krb5-1-7/src/clients/kvno/kvno.M b/krb5-1-7/src/clients/kvno/kvno.M new file mode 100644 index 000000000..b7e4d46a0 --- /dev/null +++ b/krb5-1-7/src/clients/kvno/kvno.M @@ -0,0 +1,74 @@ +.\" Copyright (C) 1998 by the FundsXpress, INC. +.\" +.\" All rights reserved. +.\" +.\" Export of this software from the United States of America may require +.\" a specific license from the United States Government. It is the +.\" responsibility of any person or organization contemplating export to +.\" obtain such a license before exporting. +.\" +.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +.\" distribute this software and its documentation for any purpose and +.\" without fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright notice and +.\" this permission notice appear in supporting documentation, and that +.\" the name of FundsXpress. not be used in advertising or publicity pertaining +.\" to distribution of the software without specific, written prior +.\" permission. FundsXpress makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" without express +.\" or implied warranty. +.\" +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" 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-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 \-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. +.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-7/src/clients/kvno/kvno.c b/krb5-1-7/src/clients/kvno/kvno.c new file mode 100644 index 000000000..b98b85d30 --- /dev/null +++ b/krb5-1-7/src/clients/kvno/kvno.c @@ -0,0 +1,278 @@ +/* + * 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 +#include +#include "autoconf.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +extern int optind; +extern char *optarg; + +static char *prog; + +static void xusage() +{ + fprintf(stderr, "usage: %s [-C] [-u] [-c ccache] [-e etype] [-k keytab] [-S sname] service1 service2 ...\n", + prog); + exit(1); +} + +int quiet = 0; + +static void do_v5_kvno (int argc, char *argv[], + char *ccachestr, char *etypestr, char *keytab_name, + char *sname, int canon, int unknown); + +#include +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 canon = 0, unknown = 0; + + + set_com_err_hook (extended_com_err_fn); + + prog = strrchr(argv[0], '/'); + prog = prog ? (prog + 1) : argv[0]; + + while ((option = getopt(argc, argv, "uCc:e:hk:qS:")) != -1) { + switch (option) { + case 'C': + canon = 1; + break; + 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 'S': + sname = optarg; + if (unknown == 1){ + fprintf(stderr, "Options -u and -S are mutually exclusive\n"); + xusage(); + } + break; + case 'u': + unknown = 1; + if (sname){ + fprintf(stderr, "Options -u and -S are mutually exclusive\n"); + xusage(); + } + break; + default: + xusage(); + break; + } + } + + if ((argc - optind) < 1) + xusage(); + + do_v5_kvno(argc - optind, argv + optind, + ccachestr, etypestr, keytab_name, sname, canon, unknown); + return 0; +} + +#include +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, int canon, int unknown) +{ + 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; + } + if (unknown == 1) { + krb5_princ_type(context, in_creds.server) = KRB5_NT_UNKNOWN; + } + + 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, canon ? KRB5_GC_CANONICALIZE : 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-7/src/config-files/Makefile.in b/krb5-1-7/src/config-files/Makefile.in new file mode 100644 index 000000000..ad2b999d9 --- /dev/null +++ b/krb5-1-7/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-7/src/config-files/convert-config-files b/krb5-1-7/src/config-files/convert-config-files new file mode 100644 index 000000000..53ddefff1 --- /dev/null +++ b/krb5-1-7/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"; + +$_ = ; +strip; +$default_realm = $_; + +while() { + 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 () { + 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-7/src/config-files/deps b/krb5-1-7/src/config-files/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/config-files/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/config-files/kdc.conf b/krb5-1-7/src/config-files/kdc.conf new file mode 100644 index 000000000..3355699ff --- /dev/null +++ b/krb5-1-7/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-7/src/config-files/kdc.conf.M b/krb5-1-7/src/config-files/kdc.conf.M new file mode 100644 index 000000000..21f173bbe --- /dev/null +++ b/krb5-1-7/src/config-files/kdc.conf.M @@ -0,0 +1,263 @@ +.\" Copyright 1995, 2008 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 iprop_enable +This +.B boolean +("true" or "false") specifies whether incremental database propagation +is enabled. The default is "false". + +.IP iprop_master_ulogsize +This +.B numeric value +specifies the maximum number of log entries to be retained for +incremental propagation. The maximum value is 2500; default is 1000. + +.IP iprop_slave_poll +This +.B delta time string +specfies how often the slave KDC polls for new updates from the +master. Default is "2m" (that is, two minutes). + +.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-7/src/config-files/krb5.conf b/krb5-1-7/src/config-files/krb5.conf new file mode 100644 index 000000000..210348fa1 --- /dev/null +++ b/krb5-1-7/src/config-files/krb5.conf @@ -0,0 +1,26 @@ +[libdefaults] + default_realm = ATHENA.MIT.EDU + +[realms] +# use "kdc = ..." if realm admins haven't put SRV records into DNS + 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 + } + +[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-7/src/config-files/krb5.conf.M b/krb5-1-7/src/config-files/krb5.conf.M new file mode 100644 index 000000000..2f2fbb239 --- /dev/null +++ b/krb5-1-7/src/config-files/krb5.conf.M @@ -0,0 +1,648 @@ +.\" 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. This value is only used for DES keys; other keys use the +preferred checksum type for those keys. + +.IP ap_req_checksum_type +If set this variable controls what ap-req checksum will be used in authenticators. This variable should be unset so the appropriate checksum for the encryption key in use will be used. This can be set if backward compatibility requires a specific checksum type. + +.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 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 realm_try_domains +Indicate whether a host's domain components should be used to +determine the Kerberos realm of the host. The value of this variable +is an integer: -1 means not to search, 0 means to try the host's +domain itself, 1 means to also try the domain's immediate parent, and +so forth. The library's usual mechanism for locating Kerberos realms +is used to determine whether a domain is a valid realm--which may +involve consulting DNS if dns_lookup_kdc is set. The default is not +to search domain components. + +.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: +.in +.5i +The principal will be looked up in the database . +Support for this is not currently compiled in by default. +.in -.5in +RULE: +.in +.5i +The local name will be formulated from . +.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= +.IP FILE: +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= +This causes the entity's logging messages to go to the specified device. +.IP SYSLOG[:[:]] +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_servers +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_servers +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-7/src/config-files/mech b/krb5-1-7/src/config-files/mech new file mode 100644 index 000000000..15c9fcd0b --- /dev/null +++ b/krb5-1-7/src/config-files/mech @@ -0,0 +1,3 @@ +#kerberos_v5 1.2.840.48018.1.2.2 mech_krb5.so +#mskrb 1.2.840.113554.1.2.2 mech_krb5.so +#spnego 1.3.6.1.5.5.2 mech_spnego.so diff --git a/krb5-1-7/src/config-files/services.append b/krb5-1-7/src/config-files/services.append new file mode 100644 index 000000000..bd1010f5c --- /dev/null +++ b/krb5-1-7/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-7/src/config/ac-archive/README b/krb5-1-7/src/config/ac-archive/README new file mode 100644 index 000000000..7bc626eb5 --- /dev/null +++ b/krb5-1-7/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-7/src/config/ac-archive/acx_pthread.m4 b/krb5-1-7/src/config/ac-archive/acx_pthread.m4 new file mode 100644 index 000000000..6a1537d47 --- /dev/null +++ b/krb5-1-7/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 and Alejandro Forero Cuervo + +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_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 ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [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-7/src/config/config.guess b/krb5-1-7/src/config/config.guess new file mode 100755 index 000000000..7924ac077 --- /dev/null +++ b/krb5-1-7/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 . +# Please send patches to . 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 ." + +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 /* 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 + + 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 + #include + + 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 + 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 + #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' /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 + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 < +# include +#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 + 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 +# 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 < 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-7/src/config/config.sub b/krb5-1-7/src/config/config.sub new file mode 100755 index 000000000..70584b007 --- /dev/null +++ b/krb5-1-7/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 . 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 ." + +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-7/src/config/install-sh b/krb5-1-7/src/config/install-sh new file mode 100755 index 000000000..f5061e7e2 --- /dev/null +++ b/krb5-1-7/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-7/src/config/lib.in b/krb5-1-7/src/config/lib.in new file mode 100644 index 000000000..22277cbb2 --- /dev/null +++ b/krb5-1-7/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 darwin.exports hpux10.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-7/src/config/libnodeps.in b/krb5-1-7/src/config/libnodeps.in new file mode 100644 index 000000000..6416a3007 --- /dev/null +++ b/krb5-1-7/src/config/libnodeps.in @@ -0,0 +1,4 @@ +# Must override when there are no dependencies, because on some +# platforms there's a prefix stuck in front of the library path that +# we won't set (SHLIB_RDIRS). +SHLIB_EXPFLAGS= diff --git a/krb5-1-7/src/config/libnover.in b/krb5-1-7/src/config/libnover.in new file mode 100644 index 000000000..5f89827e2 --- /dev/null +++ b/krb5-1-7/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)$(DYNOBJEXT) + $(RM) binutils.versions osf1.exports darwin.exports hpux10.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-7/src/config/libobj.in b/krb5-1-7/src/config/libobj.in new file mode 100644 index 000000000..7d306cd49 --- /dev/null +++ b/krb5-1-7/src/config/libobj.in @@ -0,0 +1,42 @@ +### 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) > $@ + : updated $@ + +OBJS.SH: $(SHLIBOBJS) Makefile + @echo $(SHLIBOBJS) > $@ + : updated $@ + +OBJS.PF: $(PFLIBOBJS) Makefile + @echo $(PFLIBOBJS) > $@ + : updated $@ + +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-7/src/config/libpriv.in b/krb5-1-7/src/config/libpriv.in new file mode 100644 index 000000000..c7e3443b1 --- /dev/null +++ b/krb5-1-7/src/config/libpriv.in @@ -0,0 +1,13 @@ +# Additional definitions for private libraries, which we build as archive +# libraries (or equivalent) and do not install. +# +# The defaults (for installed shared libraries) are in pre.in. We +# override them here, before lib.in uses them. +LIBLIST=lib$(LIBBASE)$(STLIBEXT) +LIBLINKS=$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT) +OBJLISTS=OBJS.ST +LIBINSTLIST= +SHLIBEXT=.so-nobuild +SHLIBVEXT=.so.v-nobuild +SHLIBSEXT=.so.s-nobuild +STLIBEXT=$(STLIBEXT_if_static) diff --git a/krb5-1-7/src/config/mkinstalldirs b/krb5-1-7/src/config/mkinstalldirs new file mode 100755 index 000000000..6b3b5fc5d --- /dev/null +++ b/krb5-1-7/src/config/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# 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-7/src/config/move-if-changed b/krb5-1-7/src/config/move-if-changed new file mode 100755 index 000000000..21403e129 --- /dev/null +++ b/krb5-1-7/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-7/src/config/post.in b/krb5-1-7/src/config/post.in new file mode 100644 index 000000000..6ac10b05f --- /dev/null +++ b/krb5-1-7/src/config/post.in @@ -0,0 +1,207 @@ +############################################################ +## 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 + +# Temporarily keep the rule for removing the dependency line eater +# until we're sure we've gotten everything converted and excised the +# old stuff from Makefile.in files. +depend-update-makefile: .depend depend-recurse + if test -n "$(SRCS)" ; then \ + $(CP) .depend $(srcdir)/deps.new ; \ + else \ + echo "# No dependencies here." > $(srcdir)/deps.new ; \ + fi + $(SRCTOP)/config/move-if-changed $(srcdir)/deps.new $(srcdir)/deps + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < $(srcdir)/Makefile.in > $(srcdir)/Makefile.in.new + $(SRCTOP)/config/move-if-changed $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in + +DEPTARGETS = .depend .d .dtmp $(DEP_VERIFY) +DEPTARGETS_CLEAN = .depend .d .dtmp $(DEPTARGETS_@srcdir@_@CONFIG_RELTOPDIR@) +DEPTARGETS_@top_srcdir@_. = $(DEP_VERIFY) + +# Clear out dependencies. Should only be used temporarily, e.g., while +# moving or renaming headers and then rebuilding dependencies. +undepend:: undepend-postrecurse +undepend-recurse: +undepend-postrecurse: undepend-recurse + if test -n "$(SRCS)" ; then \ + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < $(srcdir)/Makefile.in \ + > $(srcdir)/Makefile.in.new ;\ + echo "# +++ Dependency line eater +++" >> $(srcdir)/Makefile.in.new ;\ + echo "# (dependencies temporarily removed)" >> $(srcdir)/Makefile.in.new ;\ + $(SRCTOP)/config/move-if-changed $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in;\ + else :; fi + +# +# end dependency generation +############################## + +clean:: clean-$(WHAT) + +clean-unix:: + $(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES) et-[ch]-*.et et-[ch]-*.[ch] + -$(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 $(srcdir)/deps $(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 \ + $(SRCTOP)/aclocal.m4 + -$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache + 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 undepend-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-7/src/config/pre.in b/krb5-1-7/src/config/pre.in new file mode 100644 index 000000000..9fe2690d7 --- /dev/null +++ b/krb5-1-7/src/config/pre.in @@ -0,0 +1,569 @@ +############################################################ +## 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=/ + +# +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 +# WARN_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 \ + $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(PTHREAD_CFLAGS) +ALL_CXXFLAGS = $(DEFS) $(DEFINES) $(KRB_INCLUDES) $(LOCALINCLUDES) \ + -DKRB5_DEPRECATED=1 \ + $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(PTHREAD_CFLAGS) + +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_CXXFLAGS = @WARN_CXXFLAGS@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +THREAD_LINKOPTS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +CC = @CC@ +CXX = @CXX@ +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@ + +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_AD_MODULE_DIR = $(MODULE_DIR)/authdata +KRB5_LIBKRB5_MODULE_DIR = $(MODULE_DIR)/libkrb5 +GSS_MODULE_DIR = @libdir@/gss +KRB5_INCSUBDIRS = \ + $(KRB5_INCDIR)/kadm5 \ + $(KRB5_INCDIR)/krb5 \ + $(KRB5_INCDIR)/gssapi \ + $(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 = +MOVEIFCHANGED = $(SRCTOP)/config/move-if-changed + +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@ +CXX_LINK=@CXX_LINK@ + +# prefix (with no spaces after) for rpath flag to cc +RPATH_FLAG=@RPATH_FLAG@ + +# link flags to add PROG_RPATH to the rpath +PROG_RPATH_FLAGS=@PROG_RPATH_FLAGS@ + +# 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) +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) +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 + +# 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) + +# 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) +KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS) +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 + +# +# 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: + $(RM) et-h-$*.et et-h-$*.c et-h-$*.h + $(CP) $< et-h-$*.et + $(COMPILE_ET) et-h-$*.et + $(MV) et-h-$*.h $*.h + $(RM) et-h-$*.et et-h-$*.c +.et.c: + $(RM) et-c-$*.et et-c-$*.c et-c-$*.h + $(CP) $< et-c-$*.et + $(COMPILE_ET) et-c-$*.et + $(MV) et-c-$*.c $*.c + $(RM) et-c-$*.et et-c-$*.h + +# rule to make object files +# +.SUFFIXES: .cpp .c .o +.c.o: + $(CC) $(ALL_CFLAGS) -c $< +# Use .cpp because that's what autoconf uses in its test. +# If the compiler doesn't accept a .cpp suffix here, it wouldn't +# have accepted it when autoconf tested it. +.cpp.o: + $(CXX) $(ALL_CXXFLAGS) -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: +## +# +# These settings are for building shared libraries only. Including +# libpriv.in will override with values appropriate for static +# libraries that we don't install. Some values will depend on whether +# the platform supports major and minor version number extensions on +# shared libraries, hence the FOO_@@ settings. + +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_@SHLIB_HAVE_MINOR_VERS@) +LIBLIST_yes=lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT) +LIBLIST_no=lib$(LIBBASE)$(SHLIBEXT) + +# Set by configure; list of library symlinks to make to $(TOPLIBD) +LIBLINKS=$(LIBLINKS_@SHLIB_HAVE_MINOR_VERS@) +LIBLINKS_yes=$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT) +LIBLINKS_no=$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) + +# Set by configure; list of install targets +LIBINSTLIST=$(LIBINSTLIST_@SHLIB_HAVE_MINOR_VERS@) +LIBINSTLIST_yes=install-shlib-soname +LIBINSTLIST_no=install-shared + +# 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_if_static=@STLIBEXT@ +STLIBEXT=.a-nobuild + +# 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@ + +# run path flags for explicit libraries depending on this one, +# e.g. "-R$(SHLIB_RPATH)" +SHLIB_RPATH_FLAGS=@SHLIB_RPATH_FLAGS@ + +# flags for explicit libraries depending on this one, +# e.g. "$(SHLIB_RPATH_FLAGS) $(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=OBJS.SH + +# 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@ + +# +# 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 + +## +## end of pre.in +############################################################ diff --git a/krb5-1-7/src/config/ren2long b/krb5-1-7/src/config/ren2long new file mode 100755 index 000000000..e44dc8d5f --- /dev/null +++ b/krb5-1-7/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 ]; then echo ::mv ; mv ; 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-7/src/config/ren2long.awk b/krb5-1-7/src/config/ren2long.awk new file mode 100644 index 000000000..fcf0177ea --- /dev/null +++ b/krb5-1-7/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-7/src/config/rm.bat b/krb5-1-7/src/config/rm.bat new file mode 100644 index 000000000..4cb1c8822 --- /dev/null +++ b/krb5-1-7/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-7/src/config/shlib.conf b/krb5-1-7/src/config/shlib.conf new file mode 100644 index 000000000..6972ff060 --- /dev/null +++ b/krb5-1-7/src/config/shlib.conf @@ -0,0 +1,532 @@ +# 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. +# CXX_LINK_STATIC, CXX_LINK_SHARED: Variants for C++. +# 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)' +CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + if test "$ac_cv_c_compiler_gnu" = 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 + if test "$ac_cv_cxx_compiler_gnu" = yes \ + && test "$krb5_cv_prog_gnu_ld" = yes; then + # Really should check for gnu ld vs system ld, too. + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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. + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) -Wl,-oldstyle_liblookup $(CXXFLAGS) $(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 "$ac_cv_c_compiler_gnu" = yes; then + PICFLAGS=-fPIC + SHLIB_RPATH_FLAGS='-Wl,+b,$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='-Wl,+s $(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + LDCOMBINE='gcc -fPIC -shared -Wl,+h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-c,hpux10.exports' + else + PICFLAGS=+z + SHLIB_RPATH_FLAGS='+b $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='+s $(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + LDCOMBINE='ld -b +h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -c hpux10.exports' + fi + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -Wl,+s $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) -Wl,+s $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 "$ac_cv_c_compiler_gnu" = 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_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + # no gprof for Irix... + PROFFLAGS=-p + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 "$ac_cv_c_compiler_gnu" = 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 "$ac_cv_c_compiler_gnu" = yes \ + && test "$krb5_cv_prog_gnu_ld" = yes; then + opts='' + fi + LDCOMBINE='$(CC) -shared '$opts' -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $$initfini' + SHLIB_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + # no gprof for Irix... + PROFFLAGS=-p + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 "$ac_cv_c_compiler_gnu" = 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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + SHLIBEXT=.so + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + SHLIBEXT=.so + LDCOMBINE='ld -Bshareable' + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 + LDCOMBINE='$(CC) -undefined error -dead_strip -dynamiclib -compatibility_version $(LIBMAJOR) -current_version $(LIBMAJOR).$(LIBMINOR) -install_name "$(KRB5_LIBDIR)/$(LIBPREFIX)$(LIBBASE)$(SHLIBVEXT)" -exported_symbols_list darwin.exports $(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="" + for lib in libkrb5support.1.1.dylib libkadm5srv.5.1.dylib libkdb5.4.0.dylib; do + LDCOMBINE_TAIL="$LDCOMBINE_TAIL -dylib_file \"\$(KRB5_LIBDIR)/$lib\":\$(TOPLIBD)/$lib" + done + MAKE_DYNOBJ_COMMAND='$(CC) -bundle $(CFLAGS) $(LDFLAGS) -o $@ $$objlist $(DYNOBJ_EXPFLAGS) -exported_symbols_list darwin.exports'" ${LDCOMBINE_TAIL}" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -dynamic $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) -dynamic $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='DYLD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export DYLD_LIBRARY_PATH;' + ;; + +*-*-solaris*) + if test "$ac_cv_c_compiler_gnu" = 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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(PURE) $(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(PURE) $(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(PURE) $(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(PURE) $(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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),--no-undefined $(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_RPATH_FLAGS='-Wl,-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROG_RPATH_FLAGS='-Wl,-rpath,$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS)' + CXX_LINK_STATIC='$(CXX) $(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 "$ac_cv_c_compiler_gnu" = "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 + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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 "$ac_cv_c_compiler_gnu" = "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 + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(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-7/src/config/wconfig.pl b/krb5-1-7/src/config/wconfig.pl new file mode 100755 index 000000000..8a9d19f72 --- /dev/null +++ b/krb5-1-7/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-7/src/config/win-post.in b/krb5-1-7/src/config/win-post.in new file mode 100644 index 000000000..fd874aebe --- /dev/null +++ b/krb5-1-7/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-7/src/config/win-pre.in b/krb5-1-7/src/config/win-pre.in new file mode 100644 index 000000000..25dcaa918 --- /dev/null +++ b/krb5-1-7/src/config/win-pre.in @@ -0,0 +1,259 @@ +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) -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 +PERL=perl + +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-7/src/config/winexclude.sed b/krb5-1-7/src/config/winexclude.sed new file mode 100644 index 000000000..199cf4443 --- /dev/null +++ b/krb5-1-7/src/config/winexclude.sed @@ -0,0 +1,19 @@ +/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-7/src/configure.in b/krb5-1-7/src/configure.in new file mode 100644 index 000000000..602df94c6 --- /dev/null +++ b/krb5-1-7/src/configure.in @@ -0,0 +1,1100 @@ +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 +AC_CACHE_CHECK(if va_copy is available, krb5_cv_va_copy, +[AC_LINK_IFELSE([ +#include +void f(va_list ap) { + va_list ap2; + va_copy(ap2, ap); + va_end(ap2); +} +va_list x; +int main() +{ + f(x); + return 0; +}], krb5_cv_va_copy=yes, krb5_cv_va_copy=no)]) +if test "$krb5_cv_va_copy" = yes; then + AC_DEFINE(HAS_VA_COPY,1,[Define if va_copy macro or function is available.]) +fi +dnl +dnl Note that this isn't checking if the copied value *works*, just +dnl whether the C language constraints permit the copying. If +dnl va_list is defined as an array type, it can't be assigned. +AC_CACHE_CHECK(if va_list objects can be copied by assignment, + krb5_cv_va_simple_copy, +[AC_COMPILE_IFELSE([ +#include +void f(va_list va2) { + va_list va1; + va1 = va2; +}], krb5_cv_va_simple_copy=yes, krb5_cv_va_simple_copy=no)]) +if test "$krb5_cv_va_simple_copy" = yes; then + AC_DEFINE(CAN_COPY_VA_LIST,1,[Define if va_list objects can be simply copied by assignment.]) +fi +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 +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 +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) +AC_CHECK_FUNCS(strlcpy) +EXTRA_SUPPORT_SYMS= +AC_CHECK_FUNC(strlcpy, [STRLCPY_ST_OBJ= STRLCPY_OBJ=], [STRLCPY_ST_OBJ=strlcpy.o STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"]) +AC_SUBST(STRLCPY_OBJ) +AC_SUBST(STRLCPY_ST_OBJ) +AC_CHECK_FUNC(vasprintf, +[PRINTF_ST_OBJ= +PRINTF_OBJ=], +[PRINTF_ST_OBJ=printf.o +PRINTF_OBJ='$(OUTPRE)printf.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_asprintf krb5int_vasprintf"]) +AC_SUBST(PRINTF_OBJ) +AC_SUBST(PRINTF_ST_OBJ) +KRB5_NEED_PROTO([#include +#include +],vasprintf) +KRB5_NEED_PROTO([#include +#ifdef HAVE_UNISTD_H +#include +#endif +/* Solaris 8 declares swab in stdlib.h. */ +#include +],swab,1) +KRB5_NEED_PROTO([#include ],isblank,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 +KRB5_RUN_FLAGS +dnl +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_HEADERS(include/autoconf.h, [echo timestamp > include/autoconf.stamp]) +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) +dnl +AC_CHECK_FUNC(mkstemp, +[MKSTEMP_ST_OBJ= +MKSTEMP_OBJ=], +[MKSTEMP_ST_OBJ='mkstemp.o' +MKSTEMP_OBJ='$(OUTPRE)mkstemp.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_mkstemp"]) +AC_SUBST(MKSTEMP_OBJ) +AC_SUBST(MKSTEMP_ST_OBJ) +AC_SUBST(EXTRA_SUPPORT_SYMS) +dnl +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 +#include ]) +AC_CHECK_MEMBERS([struct stat.st_mtimensec,struct stat.st_mtimespec.tv_nsec,struct stat.st_mtim.tv_nsec],,,[#include +#include ]) +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 ],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 +#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 +#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 +#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 +#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 + 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 + 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 + extern int getpwnam_r();], [1;], + getpwnam_r_returns_int=yes,getpwnam_r_returns_int=no) + AC_TRY_COMPILE([#include + 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 + struct passwd pwx; char buf[1024];], + [getpwnam_r("", &pwx, buf, sizeof(buf));], args4=yes, args4=no) + AC_TRY_COMPILE([#include + 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 + extern int gmtime_r ();], [1;], return_int=yes, return_int=no) + AC_TRY_COMPILE([#include + 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 + 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 + 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 errno.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 +#endif +#include +#include +#include +],[ + 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 +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 +#include +],[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 +#include +],[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 +#include +#include +],[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 ], + [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]),) + +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 +#elif defined(HAVE_INTTYPES_H) +# include +#endif +]) +AC_CHECK_TYPES([struct cmsghdr, struct in_pktinfo, struct in6_pktinfo, struct sockaddr_storage], , , [ +#include +#include +#include +]) +AC_CHECK_TYPES([struct rt_msghdr], , , [ +#include +#include +#include +]) +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 types libdb2 wants +dnl +AC_CHECK_TYPES([ssize_t, u_char, u_int, u_long, u_int8_t, u_int16_t, u_int32_t, int8_t, int16_t, int32_t]) +dnl +dnl Some libdb2 test programs want a shell that supports functions. +FCTSH=false +AC_PATH_PROG(SH,sh,false) +AC_PATH_PROG(SH5,sh5,false) +AC_PATH_PROG(BASH,bash,false) +for prog in $SH $SH5 $BASH; do + AC_MSG_CHECKING(if $prog supports functions) + if $prog -c 'foo() { true; }; foo' >/dev/null 2>&1; then + AC_MSG_RESULT(yes) + FCTSH=$prog + break + else + AC_MSG_RESULT(no) + fi +done +AC_SUBST(FCTSH) +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 +#include +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 +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 lib/gssapi +AC_CHECK_HEADER(stdint.h,[ + include_stdint='awk '\''END{printf("%cinclude \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 \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 \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 ], +[struct rpcent e; +char c = e.r_name[0]; +int i = e.r_number;], +[AC_TRY_COMPILE([#include ], +[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 ' +else + GSSRPC__SYS_SELECT_H='/* #include */' +fi +AC_SUBST(GSSRPC__SYS_SELECT_H) +if test $ac_cv_header_sys_time_h = yes; then + GSSRPC__SYS_TIME_H='#include ' +else + GSSRPC__SYS_TIME_H='/* #include */' +fi +AC_SUBST(GSSRPC__SYS_TIME_H) +if test $ac_cv_header_unistd_h = yes; then + GSSRPC__UNISTD_H='#include ' +else + GSSRPC__UNISTD_H='/* #include */' +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 ], + [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 ], + [int i = MAXHOSTNAMELEN;], + [krb5_cv_header_netdb_h_maxhostnamelen=yes], + [krb5_cv_header_netdb_h_maxhostnamelen=no])]) + +GSSRPC__SYS_PARAM_H='/* #include */' +GSSRPC__NETDB_H='/* #include */' +if test $krb5_cv_header_sys_param_h_maxhostnamelen = yes; then + GSSRPC__SYS_PARAM_H='#include ' +else + if test $krb5_cv_header_netdb_h_maxhostnamelen = yes; then + GSSRPC__NETDB_H='#include ' + 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 ], + [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 ], + [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 ], + [uint32_t i = 0;], + [krb5_cv_header_inttypes_h_uint32_t=yes], + [krb5_cv_header_inttypes_h_uint32_t=no])]) +GSSRPC__STDINT_H='/* #include */' +GSSRPC__INTTYPES_H='/* #include */' +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 ' + else + if test $krb5_cv_header_inttypes_h_uint32_t = yes; then + GSSRPC__INTTYPES_H='#include ' + 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 +#if HAVE_UNISTD_H +#include +#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 +@%:@include ]) +AC_CHECK_MEMBERS([struct sockaddr.sa_len], , , + [#include +@%:@include ]) + +AC_MSG_CHECKING([return type of setrpcent]) +AC_CACHE_VAL(k5_cv_type_setrpcent, +[AC_TRY_COMPILE([#include +#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 +#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_ARG_ENABLE([pkinit], +[ --disable-pkinit disable PKINIT plugin support],, +enable_pkinit=yes) +if test "$enable_pkinit" = yes; then + AC_CACHE_CHECK(for a recent enough OpenSSL, k5_cv_openssl_version_okay, +[AC_COMPILE_IFELSE([#include +#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" +fi +if test "$k5_cv_openssl_version_okay" = yes && test "$enable_pkinit" = yes; then + K5_GEN_MAKEFILE(plugins/preauth/pkinit) +else + AC_DEFINE([DISABLE_PKINIT], 1, [Define to disable PKINIT plugin support]) + AC_MSG_NOTICE([Disabling PKINIT support.]) +fi + +dnl for lib/apputils +AC_REPLACE_FUNCS(daemon) + +dnl for tests/ +if test x"$RUNTEST" != x; then + HAVE_RUNTEST=yes +else + HAVE_RUNTEST=no +fi +AC_SUBST(HAVE_RUNTEST) + +dnl for plugins/kdb/db2 +dnl +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*) + DB_EXTRA_LIBS=-ldb + ;; +*) + DB_EXTRA_LIBS= + ;; +esac +AC_SUBST(DB_EXTRA_LIBS) + +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 +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 On the Mac we need CoreFoundation for UCS-2 conversion for RC4. +case $krb5_cv_host in +*-*-darwin* | *-*-rhapsody*) CRYPTO_LIBS="-framework CoreFoundation" ;; +*) CRYPTO_LIBS="" ;; +esac +AC_SUBST(CRYPTO_LIBS) +dnl +dnl +if test "$COM_ERR_VERSION" = k5 ; then + K5_GEN_MAKEFILE(util/et) +fi +if test "$SS_VERSION" = k5 ; then + K5_GEN_MAKEFILE(util/ss) +fi +dnl +dnl +ldap_plugin_dir="" +ldap_lib="" +if test -n "$OPENLDAP_PLUGIN"; then + AC_CHECK_HEADERS(ldap.h lber.h, :, [AC_MSG_ERROR($ac_header not found)]) + AC_CHECK_LIB(ldap, ldap_init, :, [AC_MSG_ERROR(libldap not found or missing ldap_init)]) + 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" + + 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 - cannot build LDAP database module") + fi + fi + AC_DEFINE([ENABLE_LDAP], 1, [Define if LDAP KDB support within the Kerberos library (mainly ASN.1 code) should be enabled.]) + AC_SUBST(LDAP_LIBS) + + K5_GEN_MAKEFILE(plugins/kdb/ldap) + K5_GEN_MAKEFILE(plugins/kdb/ldap/ldap_util) + K5_GEN_MAKEFILE(plugins/kdb/ldap/libkdb_ldap) + ldap_plugin_dir=plugins/kdb/ldap + LDAP=yes +else + LDAP=no +fi +AC_SUBST(ldap_plugin_dir) +AC_SUBST(LDAP) + +dnl We really should look for and use python-config. +PYTHON_LIB= +AC_CHECK_HEADERS(Python.h python2.3/Python.h python2.5/Python.h) +AC_CHECK_LIB(python2.3,main,[PYTHON_LIB=-lpython2.3], + AC_CHECK_LIB(python2.5,main,[PYTHON_LIB=-lpython2.5])) +AC_SUBST(PYTHON_LIB) + +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 +AC_CONFIG_SUBDIRS(appl/libpty appl/bsd appl/gssftp appl/telnet) + +AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config]) +V5_AC_OUTPUT_MAKEFILE(. + + util util/support util/profile util/send-pr + + lib 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/krb5/unicode + + lib/gssapi lib/gssapi/generic lib/gssapi/krb5 lib/gssapi/spnego + lib/gssapi/mechglue + + lib/rpc lib/rpc/unit-test + + lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test + + lib/apputils + + kdc slave config-files gen-manpages include + + plugins/locate/python + plugins/kdb/db2 + plugins/kdb/db2/libdb2 + plugins/kdb/db2/libdb2/hash + plugins/kdb/db2/libdb2/btree + plugins/kdb/db2/libdb2/db + plugins/kdb/db2/libdb2/mpool + plugins/kdb/db2/libdb2/recno + plugins/kdb/db2/libdb2/test + plugins/preauth/cksum_body plugins/preauth/encrypted_challenge + plugins/preauth/wpse + plugins/authdata/greet + + 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 + + appl + appl/sample appl/sample/sclient appl/sample/sserver + appl/simple appl/simple/client appl/simple/server + appl/gss-sample appl/user_user + + tests tests/resolve tests/asn.1 tests/create tests/hammer + tests/verify tests/gssapi tests/dejagnu tests/threads tests/shlib + tests/gss-threads tests/misc tests/mkeystash_compat + util/collected-client-lib +) diff --git a/krb5-1-7/src/deps b/krb5-1-7/src/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/gen-manpages/Makefile.in b/krb5-1-7/src/gen-manpages/Makefile.in new file mode 100644 index 000000000..a005278b5 --- /dev/null +++ b/krb5-1-7/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-7/src/gen-manpages/deps b/krb5-1-7/src/gen-manpages/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/gen-manpages/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/gen-manpages/header.doc b/krb5-1-7/src/gen-manpages/header.doc new file mode 100644 index 000000000..d11228786 --- /dev/null +++ b/krb5-1-7/src/gen-manpages/header.doc @@ -0,0 +1 @@ +.ds h ""Kerberos V5 release Beta 7" "MIT Project Athena" diff --git a/krb5-1-7/src/gen-manpages/k5login.M b/krb5-1-7/src/gen-manpages/k5login.M new file mode 100644 index 000000000..1c9f18c4b --- /dev/null +++ b/krb5-1-7/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-7/src/gen-manpages/kerberos.M b/krb5-1-7/src/gen-manpages/kerberos.M new file mode 100644 index 000000000..b412be570 --- /dev/null +++ b/krb5-1-7/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 . +.\" " +.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-7/src/include/CredentialsCache.h b/krb5-1-7/src/include/CredentialsCache.h new file mode 100644 index 000000000..cd573e710 --- /dev/null +++ b/krb5-1-7/src/include/CredentialsCache.h @@ -0,0 +1,1605 @@ +/* + * $Header$ + * + * Copyright 1998-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. + */ + +#ifndef __CREDENTIALSCACHE__ +#define __CREDENTIALSCACHE__ + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include + +/* Notifications which are sent when the ccache collection or a ccache change. + * Notifications are sent to the distributed notification center. + * The object for kCCAPICacheCollectionChangedNotification is NULL. + * The object for kCCAPICCacheChangedNotification is a CFString containing the + * name of the ccache. + * + * Note: Notifications are not sent if the CCacheServer crashes. */ +#define kCCAPICacheCollectionChangedNotification CFSTR ("CCAPICacheCollectionChangedNotification") +#define kCCAPICCacheChangedNotification CFSTR ("CCAPICCacheChangedNotification") +#endif + +#if defined(_WIN32) +#include +#include "win-mac.h" +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if TARGET_OS_MAC +#pragma pack(push,2) +#endif + +#if defined(_WIN32) +#define CCACHE_API __declspec(dllexport) + +#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1500 && !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 +#else +#define CCACHE_API +#endif + +/*! + * \mainpage Credentials Cache API (CCAPI) Documentation + * + * \section toc Table of Contents + * + * \li \ref introduction + * \li \ref error_handling + * \li \ref synchronization_atomicity + * \li \ref memory_management + * \li \ref opaque_types + * + * \li \ref ccapi_constants_reference + * \li \ref ccapi_types_reference + * + * \li \ref cc_context_reference + * \li \ref cc_context_f "cc_context_t Functions" + * + * \li \ref cc_ccache_reference + * \li \ref cc_ccache_f "cc_ccache_t Functions" + * + * \li \ref cc_credentials_reference + * \li \ref cc_credentials_f "cc_credentials_t Functions" + * + * \li \ref cc_ccache_iterator_reference + * \li \ref cc_ccache_iterator_f "cc_ccache_iterator_t Functions" + * + * \li \ref cc_credentials_iterator_reference + * \li \ref cc_credentials_iterator_f "cc_credentials_iterator_t Functions" + * + * \li \ref cc_string_reference + * \li \ref cc_string_f "cc_string_t Functions" + * + * \section introduction Introduction + * + * This is the specification for an API which provides Credentials Cache + * services for both Kerberos v5 and v4. The idea behind this API is that + * multiple Kerberos implementations can share a single collection of + * credentials caches, mediated by this API specification. On the Mac OS + * and Microsoft Windows platforms this will allow single-login, even when + * more than one Kerberos shared library is in use on a particular system. + * + * Abstractly, a credentials cache collection contains one or more credentials + * caches, or ccaches. A ccache is uniquely identified by its name, which is + * a string internal to the API and not intended to be presented to users. + * The user presentable identifier of a ccache is its principal. + * + * Unlike the previous versions of the API, version 3 of the API stores both + * Kerberos v4 and v5 credentials in the same ccache. + * + * At any given time, one ccache is the "default" ccache. The exact meaning + * of a default ccache is OS-specific; refer to implementation requirements + * for details. + * + * \section error_handling Error Handling + * + * All functions of the API return some of the error constants listed FIXME; + * the exact list of error constants returned by any API function is provided + * in the function descriptions below. + * + * When returning an error constant other than ccNoError or ccIteratorEnd, API + * functions never modify any of the values passed in by reference. + * + * \section synchronization_atomicity Synchronization and Atomicity + * + * Every function in the API is atomic. In order to make a series of calls + * atomic, callers should lock the ccache or cache collection they are working + * with to advise other callers not to modify that container. Note that + * advisory locks are per container so even if you have a read lock on the cache + * collection other callers can obtain write locks on ccaches in that cache + * collection. + * + * Note that iterators do not iterate over ccaches and credentials atomically + * because locking ccaches and the cache collection over every iteration would + * degrade performance considerably under high load. However, iterators do + * guarantee a consistent view of items they are iterating over. Iterators + * will never return duplicate entries or skip entries when items are removed + * or added to the container they are iterating over. + * + * An application can always lock a ccache or the cache collection to guarantee + * that other callers participating in the advisory locking system do not + * modify the ccache or cache collection. + * + * Implementations should not use copy-on-write techniques to implement locks + * because those techniques imply that same parts of the ccache collection + * remain visible to some callers even though they are not present in the + * collection, which is a potential security risk. For example, a copy-on-write + * technique might make a copy of the entire collection when a read lock is + * acquired, so as to allow the owner of the lock to access the collection in + * an apparently unmodified state, while also allowing others to make + * modifications to the collection. However, this would also enable the owner + * of the lock to indefinitely (until the expiration time) use credentials that + * have actually been deleted from the collection. + * + * \section memory_management Object Memory Management + * + * The lifetime of an object returned by the API is until release() is called + * for it. Releasing one object has no effect on existence of any other object. + * For example, a ccache obtained within a context continue to exist when the + * context is released. + * + * Every object returned by the API (cc_context_t, cc_ccache_t, cc_ccache_iterator_t, + * cc_credentials_t, cc_credentials_iterator_t, cc_string_t) is owned by the + * caller of the API, and it is the responsibility of the caller to call release() + * for every object to prevent memory leaks. + * + * \section opaque_types Opaque Types + * + * All of the opaque high-level types in CCache API are implemented as structures + * of function pointers and private data. To perform some operation on a type, the + * caller of the API has to first obtain an instance of that type, and then call the + * appropriate function pointer from that instance. For example, to call + * get_change_time() on a cc_context_t, one would call cc_initialize() which creates + * a new cc_context_t and then call its get_change_time(), like this: + * + * \code + * cc_context_t context; + * cc_int32 err = cc_initialize (&context, ccapi_version_3, nil, nil); + * if (err == ccNoError) + * time = context->functions->get_change_time (context) + * \endcode + * + * All API functions also have convenience preprocessor macros, which make the API + * seem completely function-based. For example, cc_context_get_change_time + * (context, time) is equivalent to context->functions->get_change_time + * (context, time). The convenience macros follow the following naming convention: + * + * The API function some_function() + * \code + * cc_type_t an_object; + * result = an_object->functions->some_function (opaque_pointer, args) + * \endcode + * + * has an equivalent convenience macro of the form cc_type_some_function(): + * \code + * cc_type_t an_object; + * result = cc_type_some_function (an_object, args) + * \endcode + * + * The specifications below include the names for both the functions and the + * convenience macros, in that order. For clarity, it is recommended that clients + * using the API use the convenience macros, but that is merely a stylistic choice. + * + * Implementing the API in this manner allows us to extend and change the interface + * in the future, while preserving compatibility with older clients. + * + * For example, consider the case when the signature or the semantics of a cc_ccache_t + * function is changed. The API version number is incremented. The library + * implementation contains both a function with the old signature and semantics and + * a function with the new signature and semantics. When a context is created, the API + * version number used in that context is stored in the context, and therefore it can + * be used whenever a ccache is created in that context. When a ccache is created in a + * context with the old API version number, the function pointer structure for the + * ccache is filled with pointers to functions implementing the old semantics; when a + * ccache is created in a context with the new API version number, the function pointer + * structure for the ccache is filled with poitners to functions implementing the new + * semantics. + * + * Similarly, if a function is added to the API, the version number in the context can + * be used to decide whether to include the implementation of the new function in the + * appropriate function pointer structure or not. + */ + +/*! + * \defgroup ccapi_constants_reference Constants + * @{ + */ + +/*! + * API version numbers + * + * These constants are passed into cc_initialize() to indicate the version + * of the API the caller wants to use. + * + * CCAPI v1 and v2 are deprecated and should not be used. + */ +enum { + ccapi_version_2 = 2, + ccapi_version_3 = 3, + ccapi_version_4 = 4, + ccapi_version_5 = 5, + ccapi_version_6 = 6, + ccapi_version_7 = 7, + ccapi_version_max = ccapi_version_7 +}; + +/*! + * Error codes + */ +enum { + + ccNoError = 0, /*!< Success. */ + + ccIteratorEnd = 201, /*!< Iterator is done iterating. */ + ccErrBadParam, /*!< Bad parameter (NULL or invalid pointer where valid pointer expected). */ + ccErrNoMem, /*!< Not enough memory to complete the operation. */ + ccErrInvalidContext, /*!< Context is invalid (e.g., it was released). */ + ccErrInvalidCCache, /*!< CCache is invalid (e.g., it was released or destroyed). */ + + /* 206 */ + ccErrInvalidString, /*!< String is invalid (e.g., it was released). */ + ccErrInvalidCredentials, /*!< Credentials are invalid (e.g., they were released), or they have a bad version. */ + ccErrInvalidCCacheIterator, /*!< CCache iterator is invalid (e.g., it was released). */ + ccErrInvalidCredentialsIterator, /*!< Credentials iterator is invalid (e.g., it was released). */ + ccErrInvalidLock, /*!< Lock is invalid (e.g., it was released). */ + + /* 211 */ + ccErrBadName, /*!< Bad credential cache name format. */ + ccErrBadCredentialsVersion, /*!< Credentials version is invalid. */ + ccErrBadAPIVersion, /*!< Unsupported API version. */ + ccErrContextLocked, /*!< Context is already locked. */ + ccErrContextUnlocked, /*!< Context is not locked by the caller. */ + + /* 216 */ + ccErrCCacheLocked, /*!< CCache is already locked. */ + ccErrCCacheUnlocked, /*!< CCache is not locked by the caller. */ + ccErrBadLockType, /*!< Bad lock type. */ + ccErrNeverDefault, /*!< CCache was never default. */ + ccErrCredentialsNotFound, /*!< Matching credentials not found in the ccache. */ + + /* 221 */ + ccErrCCacheNotFound, /*!< Matching ccache not found in the collection. */ + ccErrContextNotFound, /*!< Matching cache collection not found. */ + ccErrServerUnavailable, /*!< CCacheServer is unavailable. */ + ccErrServerInsecure, /*!< CCacheServer has detected that it is running as the wrong user. */ + ccErrServerCantBecomeUID, /*!< CCacheServer failed to start running as the user. */ + + /* 226 */ + ccErrTimeOffsetNotSet, /*!< KDC time offset not set for this ccache. */ + ccErrBadInternalMessage, /*!< The client and CCacheServer can't communicate (e.g., a version mismatch). */ + ccErrNotImplemented, /*!< API function not supported by this implementation. */ + ccErrClientNotFound /*!< CCacheServer has no record of the caller's process (e.g., the server crashed). */ +}; + +/*! + * Credentials versions + * + * These constants are used in several places in the API to discern + * between Kerberos v4 and Kerberos v5. Not all values are valid + * inputs and outputs for all functions; function specifications + * below detail the allowed values. + * + * Kerberos version constants will always be a bit-field, and can be + * tested as such; for example the following test will tell you if + * a ccacheVersion includes v5 credentials: + * + * if ((ccacheVersion & cc_credentials_v5) != 0) + */ +enum cc_credential_versions { + cc_credentials_v4 = 1, + cc_credentials_v5 = 2, + cc_credentials_v4_v5 = 3 +}; + +/*! + * Lock types + * + * These constants are used in the locking functions to describe the + * type of lock requested. Note that all CCAPI locks are advisory + * so only callers using the lock calls will be blocked by each other. + * This is because locking functions were introduced after the CCAPI + * came into common use and we did not want to break existing callers. + */ +enum cc_lock_types { + cc_lock_read = 0, + cc_lock_write = 1, + cc_lock_upgrade = 2, + cc_lock_downgrade = 3 +}; + +/*! + * Locking Modes + * + * These constants are used in the advisory locking functions to + * describe whether or not the lock function should block waiting for + * a lock or return an error immediately. For example, attempting to + * acquire a lock with a non-blocking call will result in an error if the + * lock cannot be acquired; otherwise, the call will block until the lock + * can be acquired. + */ +enum cc_lock_modes { + cc_lock_noblock = 0, + cc_lock_block = 1 +}; + +/*! + * Sizes of fields in cc_credentials_v4_t. + */ +enum { + /* Make sure all of these are multiples of four (for alignment sanity) */ + cc_v4_name_size = 40, + cc_v4_instance_size = 40, + cc_v4_realm_size = 40, + cc_v4_ticket_size = 1254, + cc_v4_key_size = 8 +}; + +/*! + * String to key type (Kerberos v4 only) + */ +enum cc_string_to_key_type { + cc_v4_stk_afs = 0, + cc_v4_stk_des = 1, + cc_v4_stk_columbia_special = 2, + cc_v4_stk_krb5 = 3, + cc_v4_stk_unknown = 4 +}; + +/*!@}*/ + +/*! + * \defgroup ccapi_types_reference Basic Types + * @{ + */ + +/*! Unsigned 32-bit integer type */ +typedef uint32_t cc_uint32; +/*! Signed 32-bit integer type */ +typedef int32_t cc_int32; +#if defined (WIN32) +typedef __int64 cc_int64; +typedef unsigned __int64 cc_uint64; +#else +/*! Unsigned 64-bit integer type */ +typedef int64_t cc_int64; +/*! Signed 64-bit integer type */ +typedef uint64_t cc_uint64; +#endif +/*! + * The cc_time_t type is used to represent a time in seconds. The time must + * be stored as the number of seconds since midnight GMT on January 1, 1970. + */ +typedef cc_uint32 cc_time_t; + +/*!@}*/ + +/*! + * \defgroup cc_context_reference cc_context_t Overview + * @{ + * + * The cc_context_t type gives the caller access to a ccache collection. + * Before being able to call any functions in the CCache API, the caller + * needs to acquire an instance of cc_context_t by calling cc_initialize(). + * + * For API function documentation see \ref cc_context_f. + */ +struct cc_context_f; +typedef struct cc_context_f cc_context_f; + +struct cc_context_d { + const cc_context_f *functions; +#if TARGET_OS_MAC + const cc_context_f *vector_functions; +#endif +}; +typedef struct cc_context_d cc_context_d; +typedef cc_context_d *cc_context_t; + +/*!@}*/ + +/*! + * \defgroup cc_ccache_reference cc_ccache_t Overview + * @{ + * + * The cc_ccache_t type represents a reference to a ccache. + * Callers can access a ccache and the credentials stored in it + * via a cc_ccache_t. A cc_ccache_t can be acquired via + * cc_context_open_ccache(), cc_context_open_default_ccache(), or + * cc_ccache_iterator_next(). + * + * For API function documentation see \ref cc_ccache_f. + */ +struct cc_ccache_f; +typedef struct cc_ccache_f cc_ccache_f; + +struct cc_ccache_d { + const cc_ccache_f *functions; +#if TARGET_OS_MAC + const cc_ccache_f *vector_functions; +#endif +}; +typedef struct cc_ccache_d cc_ccache_d; +typedef cc_ccache_d *cc_ccache_t; + +/*!@}*/ + +/*! + * \defgroup cc_ccache_iterator_reference cc_ccache_iterator_t Overview + * @{ + * + * The cc_ccache_iterator_t type represents an iterator that + * iterates over a set of ccaches and returns them in all in some + * order. A new instance of this type can be obtained by calling + * cc_context_new_ccache_iterator(). + * + * For API function documentation see \ref cc_ccache_iterator_f. + */ +struct cc_ccache_iterator_f; +typedef struct cc_ccache_iterator_f cc_ccache_iterator_f; + +struct cc_ccache_iterator_d { + const cc_ccache_iterator_f *functions; +#if TARGET_OS_MAC + const cc_ccache_iterator_f *vector_functions; +#endif +}; +typedef struct cc_ccache_iterator_d cc_ccache_iterator_d; +typedef cc_ccache_iterator_d *cc_ccache_iterator_t; +/*!@}*/ + +/*! + * \defgroup cc_credentials_reference cc_credentials_t Overview + * @{ + * + * The cc_credentials_t type is used to store a single set of + * credentials for either Kerberos v4 or Kerberos v5. In addition + * to its only function, release(), it contains a pointer to a + * cc_credentials_union structure. A cc_credentials_union + * structure contains an integer of the enumerator type + * cc_credentials_version, which is either #cc_credentials_v4 or + * #cc_credentials_v5, and a pointer union, which contains either a + * cc_credentials_v4_t pointer or a cc_credentials_v5_t pointer, + * depending on the value in version. + * + * Variables of the type cc_credentials_t are allocated by the CCAPI + * implementation, and should be released with their release() + * function. API functions which receive credentials structures + * from the caller always accept cc_credentials_union, which is + * allocated by the caller, and accordingly disposed by the caller. + * + * For API functions see \ref cc_credentials_f. + */ + +/*! + * If a cc_credentials_t variable is used to store Kerberos v4 + * credentials, then credentials.credentials_v4 points to a v4 + * credentials structure. This structure is similar to a + * krb4 API CREDENTIALS structure. + */ +struct cc_credentials_v4_t { + cc_uint32 version; + /*! A properly quoted string representation of the first component of the client principal */ + char principal [cc_v4_name_size]; + /*! A properly quoted string representation of the second component of the client principal */ + char principal_instance [cc_v4_instance_size]; + /*! A properly quoted string representation of the first component of the service principal */ + char service [cc_v4_name_size]; + /*! A properly quoted string representation of the second component of the service principal */ + char service_instance [cc_v4_instance_size]; + /*! A properly quoted string representation of the realm */ + char realm [cc_v4_realm_size]; + /*! Ticket session key */ + unsigned char session_key [cc_v4_key_size]; + /*! Key version number */ + cc_int32 kvno; + /*! String to key type used. See cc_string_to_key_type for valid values */ + cc_int32 string_to_key_type; + /*! Time when the ticket was issued */ + cc_time_t issue_date; + /*! Ticket lifetime in 5 minute units */ + cc_int32 lifetime; + /*! IPv4 address of the client the ticket was issued for */ + cc_uint32 address; + /*! Ticket size (no greater than cc_v4_ticket_size) */ + cc_int32 ticket_size; + /*! Ticket data */ + unsigned char ticket [cc_v4_ticket_size]; +}; +typedef struct cc_credentials_v4_t cc_credentials_v4_t; + +/*! + * The CCAPI data structure. This structure is similar to a krb5_data structure. + * In a v5 credentials structure, cc_data structures are used + * to store tagged variable-length binary data. Specifically, + * for cc_credentials_v5.ticket and + * cc_credentials_v5.second_ticket, the cc_data.type field must + * be zero. For the cc_credentials_v5.addresses, + * cc_credentials_v5.authdata, and cc_credentials_v5.keyblock, + * the cc_data.type field should be the address type, + * authorization data type, and encryption type, as defined by + * the Kerberos v5 protocol definition. + */ +struct cc_data { + /*! The type of the data as defined by the krb5_data structure. */ + cc_uint32 type; + /*! The length of \a data. */ + cc_uint32 length; + /*! The data buffer. */ + void* data; +}; +typedef struct cc_data cc_data; + +/*! + * If a cc_credentials_t variable is used to store Kerberos v5 c + * redentials, and then credentials.credentials_v5 points to a + * v5 credentials structure. This structure is similar to a + * krb5_creds structure. + */ +struct cc_credentials_v5_t { + /*! A properly quoted string representation of the client principal. */ + char* client; + /*! A properly quoted string representation of the service principal. */ + char* server; + /*! Session encryption key info. */ + cc_data keyblock; + /*! The time when the ticket was issued. */ + cc_time_t authtime; + /*! The time when the ticket becomes valid. */ + cc_time_t starttime; + /*! The time when the ticket expires. */ + cc_time_t endtime; + /*! The time when the ticket becomes no longer renewable (if renewable). */ + cc_time_t renew_till; + /*! 1 if the ticket is encrypted in another ticket's key, or 0 otherwise. */ + cc_uint32 is_skey; + /*! Ticket flags, as defined by the Kerberos 5 API. */ + cc_uint32 ticket_flags; + /*! The the list of network addresses of hosts that are allowed to authenticate + * using this ticket. */ + cc_data** addresses; + /*! Ticket data. */ + cc_data ticket; + /*! Second ticket data. */ + cc_data second_ticket; + /*! Authorization data. */ + cc_data** authdata; +}; +typedef struct cc_credentials_v5_t cc_credentials_v5_t; + +struct cc_credentials_union { + /*! The credentials version of this credentials object. */ + cc_uint32 version; + /*! The credentials. */ + union { + /*! If \a version is #cc_credentials_v4, a pointer to a cc_credentials_v4_t. */ + cc_credentials_v4_t* credentials_v4; + /*! If \a version is #cc_credentials_v5, a pointer to a cc_credentials_v5_t. */ + cc_credentials_v5_t* credentials_v5; + } credentials; +}; +typedef struct cc_credentials_union cc_credentials_union; + +struct cc_credentials_f; +typedef struct cc_credentials_f cc_credentials_f; + +struct cc_credentials_d { + const cc_credentials_union *data; + const cc_credentials_f *functions; +#if TARGET_OS_MAC + const cc_credentials_f *otherFunctions; +#endif +}; +typedef struct cc_credentials_d cc_credentials_d; +typedef cc_credentials_d *cc_credentials_t; +/*!@}*/ + +/*! + * \defgroup cc_credentials_iterator_reference cc_credentials_iterator_t + * @{ + * The cc_credentials_iterator_t type represents an iterator that + * iterates over a set of credentials. A new instance of this type + * can be obtained by calling cc_ccache_new_credentials_iterator(). + * + * For API function documentation see \ref cc_credentials_iterator_f. + */ +struct cc_credentials_iterator_f; +typedef struct cc_credentials_iterator_f cc_credentials_iterator_f; + +struct cc_credentials_iterator_d { + const cc_credentials_iterator_f *functions; +#if TARGET_OS_MAC + const cc_credentials_iterator_f *vector_functions; +#endif +}; +typedef struct cc_credentials_iterator_d cc_credentials_iterator_d; +typedef cc_credentials_iterator_d *cc_credentials_iterator_t; +/*!@}*/ + +/*! + * \defgroup cc_string_reference cc_string_t Overview + * @{ + * The cc_string_t represents a C string returned by the API. + * It has a pointer to the string data and a release() function. + * This type is used for both principal names and ccache names + * returned by the API. Principal names may contain UTF-8 encoded + * strings for internationalization purposes. + * + * For API function documentation see \ref cc_string_f. + */ +struct cc_string_f; +typedef struct cc_string_f cc_string_f; + +struct cc_string_d { + const char *data; + const cc_string_f *functions; +#if TARGET_OS_MAC + const cc_string_f *vector_functions; +#endif +}; +typedef struct cc_string_d cc_string_d; +typedef cc_string_d *cc_string_t; +/*!@}*/ + +/*! + * Function pointer table for cc_context_t. For more information see + * \ref cc_context_reference. + */ +struct cc_context_f { + /*! + * \param io_context the context object to free. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_release(): Release memory associated with a cc_context_t. + */ + cc_int32 (*release) (cc_context_t io_context); + + /*! + * \param in_context the context object for the cache collection to examine. + * \param out_time on exit, the time of the most recent change for the entire ccache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_get_change_time(): Get the last time the cache collection changed. + * + * This function returns the time of the most recent change for the entire ccache collection. + * By maintaining a local copy the caller can deduce whether or not the ccache collection has + * been modified since the previous call to cc_context_get_change_time(). + * + * The time returned by cc_context_get_changed_time() increases whenever: + * + * \li a ccache is created + * \li a ccache is destroyed + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the default ccache is changed + * + * \note In order to be able to compare two values returned by cc_context_get_change_time(), + * the caller must use the same context to acquire them. Callers should maintain a single + * context in memory for cc_context_get_change_time() calls rather than creating a new + * context for every call. + * + * \sa wait_for_change + */ + cc_int32 (*get_change_time) (cc_context_t in_context, + cc_time_t *out_time); + + /*! + * \param in_context the context object for the cache collection. + * \param out_name on exit, the name of the default ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_get_default_ccache_name(): Get the name of the default ccache. + * + * This function returns the name of the default ccache. When the default ccache + * exists, its name is returned. If there are no ccaches in the collection, and + * thus there is no default ccache, the name that the default ccache should have + * is returned. The ccache with that name will be used as the default ccache by + * all processes which initialized Kerberos libraries before the ccache was created. + * + * If there is no default ccache, and the client is creating a new ccache, it + * should be created with the default name. If there already is a default ccache, + * and the client wants to create a new ccache (as opposed to reusing an existing + * ccache), it should be created with any unique name; #create_new_ccache() + * can be used to accomplish that more easily. + * + * If the first ccache is created with a name other than the default name, then + * the processes already running will not notice the credentials stored in the + * new ccache, which is normally undesirable. + */ + cc_int32 (*get_default_ccache_name) (cc_context_t in_context, + cc_string_t *out_name); + + /*! + * \param in_context the context object for the cache collection. + * \param in_name the name of the ccache to open. + * \param out_ccache on exit, a ccache object for the ccache + * \return On success, #ccNoError. If no ccache named \a in_name exists, + * #ccErrCCacheNotFound. On failure, an error code representing the failure. + * \brief \b cc_context_open_ccache(): Open a ccache. + * + * Opens an already existing ccache identified by its name. It returns a reference + * to the ccache in \a out_ccache. + * + * The list of all ccache names, principals, and credentials versions may be retrieved + * by calling cc_context_new_cache_iterator(), cc_ccache_get_name(), + * cc_ccache_get_principal(), and cc_ccache_get_cred_version(). + */ + cc_int32 (*open_ccache) (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param out_ccache on exit, a ccache object for the default ccache + * \return On success, #ccNoError. If no default ccache exists, + * #ccErrCCacheNotFound. On failure, an error code representing the failure. + * \brief \b cc_context_open_default_ccache(): Open the default ccache. + * + * Opens the default ccache. It returns a reference to the ccache in *ccache. + * + * This function performs the same function as calling + * cc_context_get_default_ccache_name followed by cc_context_open_ccache, + * but it performs it atomically. + */ + cc_int32 (*open_default_ccache) (cc_context_t in_context, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_name the name of the new ccache to create + * \param in_cred_vers the version of the credentials the new ccache will hold + * \param in_principal the client principal of the credentials the new ccache will hold + * \param out_ccache on exit, a ccache object for the newly created ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_ccache(): Create a new ccache. + * + * Create a new credentials cache. The ccache is uniquely identified by its name. + * The principal given is also associated with the ccache and the credentials + * version specified. A NULL name is not allowed (and ccErrBadName is returned + * if one is passed in). Only cc_credentials_v4 and cc_credentials_v5 are valid + * input values for cred_vers. If you want to create a new ccache that will hold + * both versions of credentials, call cc_context_create_ccache() with one version, + * and then cc_ccache_set_principal() with the other version. + * + * If you want to create a new ccache (with a unique name), you should use + * cc_context_create_new_ccache() instead. If you want to create or reinitialize + * the default cache, you should use cc_context_create_default_ccache(). + * + * If name is non-NULL and there is already a ccache named name: + * + * \li the credentials in the ccache whose version is cred_vers are removed + * \li the principal (of the existing ccache) associated with cred_vers is set to principal + * \li a handle for the existing ccache is returned and all existing handles for the ccache remain valid + * + * If no ccache named name already exists: + * + * \li a new empty ccache is created + * \li the principal of the new ccache associated with cred_vers is set to principal + * \li a handle for the new ccache is returned + * + * For a new ccache, the name should be any unique string. The name is not + * intended to be presented to users. + * + * If the created ccache is the first ccache in the collection, it is made + * the default ccache. Note that normally it is undesirable to create the first + * ccache with a name different from the default ccache name (as returned by + * cc_context_get_default_ccache_name()); see the description of + * cc_context_get_default_ccache_name() for details. + * + * The principal should be a C string containing an unparsed Kerberos principal + * in the format of the appropriate Kerberos version, i.e. \verbatim foo.bar/@BAZ + * \endverbatim for Kerberos v4 and \verbatim foo/bar/@BAZ \endverbatim + * for Kerberos v5. + */ + cc_int32 (*create_ccache) (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_cred_vers the version of the credentials the new default ccache will hold + * \param in_principal the client principal of the credentials the new default ccache will hold + * \param out_ccache on exit, a ccache object for the newly created default ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_default_ccache(): Create a new default ccache. + * + * Create the default credentials cache. The behavior of this function is + * similar to that of cc_create_ccache(). If there is a default ccache + * (which is always the case except when there are no ccaches at all in + * the collection), it is initialized with the specified credentials version + * and principal, as per cc_create_ccache(); otherwise, a new ccache is + * created, and its name is the name returned by + * cc_context_get_default_ccache_name(). + */ + cc_int32 (*create_default_ccache) (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_cred_vers the version of the credentials the new ccache will hold + * \param in_principal the client principal of the credentials the new ccache will hold + * \param out_ccache on exit, a ccache object for the newly created ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_new_ccache(): Create a new uniquely named ccache. + * + * Create a new unique credentials cache. The behavior of this function + * is similar to that of cc_create_ccache(). If there are no ccaches, and + * therefore no default ccache, the new ccache is created with the default + * ccache name as would be returned by get_default_ccache_name(). If there + * are some ccaches, and therefore there is a default ccache, the new ccache + * is created with a new unique name. Clearly, this function never reinitializes + * a ccache, since it always uses a unique name. + */ + cc_int32 (*create_new_ccache) (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param out_iterator on exit, a ccache iterator object for the ccache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_new_ccache_iterator(): Get an iterator for the cache collection. + * + * Used to allocate memory and initialize iterator. Successive calls to iterator's + * next() function will return ccaches in the collection. + * + * If changes are made to the collection while an iterator is being used + * on it, the iterator must return at least the intersection, and at most + * the union, of the set of ccaches that were present when the iteration + * began and the set of ccaches that are present when it ends. + */ + cc_int32 (*new_ccache_iterator) (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator); + + /*! + * \param in_context the context object for the cache collection. + * \param in_lock_type the type of lock to obtain. + * \param in_block whether or not the function should block if the lock cannot be obtained immediately. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_lock(): Lock the cache collection. + * + * Attempts to acquire an advisory lock for the ccache collection. Allowed values + * for lock_type are: + * + * \li cc_lock_read: a read lock. + * \li cc_lock_write: a write lock + * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock + * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock + * + * If block is cc_lock_block, lock() will not return until the lock is acquired. + * If block is cc_lock_noblock, lock() will return immediately, either acquiring + * the lock and returning ccNoError, or failing to acquire the lock and returning + * an error explaining why. + * + * Locks apply only to the list of ccaches, not the contents of those ccaches. To + * prevent callers participating in the advisory locking from changing the credentials + * in a cache you must also lock that ccache with cc_ccache_lock(). This is so + * that you can get the list of ccaches without preventing applications from + * simultaneously obtaining service tickets. + * + * To avoid having to deal with differences between thread semantics on different + * platforms, locks are granted per context, rather than per thread or per process. + * That means that different threads of execution have to acquire separate contexts + * in order to be able to synchronize with each other. + * + * The lock should be unlocked by using cc_context_unlock(). + * + * \note All locks are advisory. For example, callers which do not call + * cc_context_lock() and cc_context_unlock() will not be prevented from writing + * to the cache collection when you have a read lock. This is because the CCAPI + * locking was added after the first release and thus adding mandatory locks would + * have changed the user experience and performance of existing applications. + */ + cc_int32 (*lock) (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block); + + /*! + * \param in_context the context object for the cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_unlock(): Unlock the cache collection. + */ + cc_int32 (*unlock) (cc_context_t in_cc_context); + + /*! + * \param in_context a context object. + * \param in_compare_to_context a context object to compare with \a in_context. + * \param out_equal on exit, whether or not the two contexts refer to the same cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_compare(): Compare two context objects. + */ + cc_int32 (*compare) (cc_context_t in_cc_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal); + + /*! + * \param in_context a context object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_wait_for_change(): Wait for the next change in the cache collection. + * + * This function blocks until the next change is made to the cache collection + * ccache collection. By repeatedly calling cc_context_wait_for_change() from + * a worker thread the caller can effectively receive callbacks whenever the + * cache collection changes. This is considerably more efficient than polling + * with cc_context_get_change_time(). + * + * cc_context_wait_for_change() will return whenever: + * + * \li a ccache is created + * \li a ccache is destroyed + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the default ccache is changed + * + * \note In order to make sure that the caller doesn't miss any changes, + * cc_context_wait_for_change() always returns immediately after the first time it + * is called on a new context object. Callers must use the same context object + * for successive calls to cc_context_wait_for_change() rather than creating a new + * context for every call. + * + * \sa get_change_time + */ + cc_int32 (*wait_for_change) (cc_context_t in_cc_context); +}; + +/*! + * Function pointer table for cc_ccache_t. For more information see + * \ref cc_ccache_reference. + */ +struct cc_ccache_f { + /*! + * \param io_ccache the ccache object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_release(): Release memory associated with a cc_ccache_t object. + * \note Does not modify the ccache. If you wish to remove the ccache see cc_ccache_destroy(). + */ + cc_int32 (*release) (cc_ccache_t io_ccache); + + /*! + * \param io_ccache the ccache object to destroy and release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_destroy(): Destroy a ccache. + * + * Destroy the ccache referred to by \a io_ccache and releases memory associated with + * the \a io_ccache object. After this call \a io_ccache becomes invalid. If + * \a io_ccache was the default ccache, the next ccache in the cache collection (if any) + * becomes the new default. + */ + cc_int32 (*destroy) (cc_ccache_t io_ccache); + + /*! + * \param io_ccache a ccache object to make the new default ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_default(): Make a ccache the default ccache. + */ + cc_int32 (*set_default) (cc_ccache_t io_ccache); + + /*! + * \param in_ccache a ccache object. + * \param out_credentials_version on exit, the credentials version of \a in_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_credentials_version(): Get the credentials version of a ccache. + * + * cc_ccache_get_credentials_version() returns one value of the enumerated type + * cc_credentials_vers. The possible return values are #cc_credentials_v4 + * (if ccache's v4 principal has been set), #cc_credentials_v5 + * (if ccache's v5 principal has been set), or #cc_credentials_v4_v5 + * (if both ccache's v4 and v5 principals have been set). A ccache's + * principal is set with one of cc_context_create_ccache(), + * cc_context_create_new_ccache(), cc_context_create_default_ccache(), or + * cc_ccache_set_principal(). + */ + cc_int32 (*get_credentials_version) (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version); + + /*! + * \param in_ccache a ccache object. + * \param out_name on exit, a cc_string_t representing the name of \a in_ccache. + * \a out_name must be released with cc_string_release(). + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_name(): Get the name of a ccache. + */ + cc_int32 (*get_name) (cc_ccache_t in_ccache, + cc_string_t *out_name); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the principal for. + * \param out_principal on exit, a cc_string_t representing the principal of \a in_ccache. + * \a out_principal must be released with cc_string_release(). + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_principal(): Get the principal of a ccache. + * + * Return the principal for the ccache that was set via cc_context_create_ccache(), + * cc_context_create_default_ccache(), cc_context_create_new_ccache(), or + * cc_ccache_set_principal(). Principals for v4 and v5 are separate, but + * should be kept synchronized for each ccache; they can be retrieved by + * passing cc_credentials_v4 or cc_credentials_v5 in cred_vers. Passing + * cc_credentials_v4_v5 will result in the error ccErrBadCredentialsVersion. + */ + cc_int32 (*get_principal) (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal); + + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to set the principal for. + * \param in_principal a C string representing the new principal of \a in_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_principal(): Set the principal of a ccache. + * + * Set the a principal for ccache. The v4 and v5 principals can be set + * independently, but they should always be kept equal, up to differences in + * string representation between v4 and v5. Passing cc_credentials_v4_v5 in + * cred_vers will result in the error ccErrBadCredentialsVersion. + */ + cc_int32 (*set_principal) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal); + + /*! + * \param io_ccache a ccache object. + * \param in_credentials_union the credentials to store in \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_store_credentials(): Store credentials in a ccache. + * + * Store a copy of credentials in the ccache. + * + * See the description of the credentials types for the meaning of + * cc_credentials_union fields. + * + * Before credentials of a specific credential type can be stored in a ccache, + * the corresponding principal version has to be set. For example, before you can + * store Kerberos v4 credentials in a ccache, the Kerberos v4 principal has to be set + * either by cc_context_create_ccache(), cc_context_create_default_ccache(), + * cc_context_create_new_ccache(), or cc_ccache_set_principal(); likewise for + * Kerberos v5. Otherwise, ccErrBadCredentialsVersion is returned. + */ + cc_int32 (*store_credentials) (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union); + + /*! + * \param io_ccache a ccache object. + * \param in_credentials the credentials to remove from \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_remove_credentials(): Remove credentials from a ccache. + * + * Removes credentials from a ccache. Note that credentials must be previously + * acquired from the CCache API; only exactly matching credentials will be + * removed. (This places the burden of determining exactly which credentials + * to remove on the caller, but ensures there is no ambigity about which + * credentials will be removed.) cc_credentials_t objects can be obtained by + * iterating over the ccache's credentials with cc_ccache_new_credentials_iterator(). + * + * If found, the credentials are removed from the ccache. The credentials + * parameter is not modified and should be freed by the caller. It is + * legitimate to call this function while an iterator is traversing the + * ccache, and the deletion of a credential already returned by + * cc_credentials_iterator_next() will not disturb sequence of credentials + * returned by cc_credentials_iterator_next(). + */ + cc_int32 (*remove_credentials) (cc_ccache_t io_ccache, + cc_credentials_t in_credentials); + + /*! + * \param in_ccache a ccache object. + * \param out_credentials_iterator a credentials iterator for \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_new_credentials_iterator(): Iterate over credentials in a ccache. + * + * Allocates memory for iterator and initializes it. Successive calls to + * cc_credentials_iterator_next() will return credentials from the ccache. + * + * If changes are made to the ccache while an iterator is being used on it, + * the iterator must return at least the intersection, and at most the union, + * of the set of credentials that were in the ccache when the iteration began + * and the set of credentials that are in the ccache when it ends. + */ + cc_int32 (*new_credentials_iterator) (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator); + + /*! + * \param io_source_ccache a ccache object to move. + * \param io_destination_ccache a ccache object replace with the contents of \a io_source_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_move(): Move the contents of one ccache into another, destroying the source. + * + * cc_ccache_move() atomically copies the credentials, credential versions and principals + * from one ccache to another. On successful completion \a io_source_ccache will be + * released and the ccache it points to will be destroyed. Any credentials previously + * in \a io_destination_ccache will be replaced with credentials from \a io_source_ccache. + * The only part of \a io_destination_ccache which remains constant is the name. Any other + * callers referring to \a io_destination_ccache will suddenly see new data in it. + * + * Typically cc_ccache_move() is used when the caller wishes to safely overwrite the + * contents of a ccache with new data which requires several steps to generate. + * cc_ccache_move() allows the caller to create a temporary ccache + * (which can be destroyed if any intermediate step fails) and the atomically copy + * the temporary cache into the destination. + */ + cc_int32 (*move) (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache); + + /*! + * \param io_ccache the ccache object for the ccache you wish to lock. + * \param in_lock_type the type of lock to obtain. + * \param in_block whether or not the function should block if the lock cannot be obtained immediately. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_lock(): Lock a ccache. + * + * Attempts to acquire an advisory lock for a ccache. Allowed values for lock_type are: + * + * \li cc_lock_read: a read lock. + * \li cc_lock_write: a write lock + * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock + * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock + * + * If block is cc_lock_block, lock() will not return until the lock is acquired. + * If block is cc_lock_noblock, lock() will return immediately, either acquiring + * the lock and returning ccNoError, or failing to acquire the lock and returning + * an error explaining why. + * + * To avoid having to deal with differences between thread semantics on different + * platforms, locks are granted per ccache, rather than per thread or per process. + * That means that different threads of execution have to acquire separate contexts + * in order to be able to synchronize with each other. + * + * The lock should be unlocked by using cc_ccache_unlock(). + * + * \note All locks are advisory. For example, callers which do not call + * cc_ccache_lock() and cc_ccache_unlock() will not be prevented from writing + * to the ccache when you have a read lock. This is because the CCAPI + * locking was added after the first release and thus adding mandatory locks would + * have changed the user experience and performance of existing applications. + */ + cc_int32 (*lock) (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block); + + /*! + * \param io_ccache a ccache object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_unlock(): Unlock a ccache. + */ + cc_int32 (*unlock) (cc_ccache_t io_ccache); + + /*! + * \param in_ccache a cache object. + * \param out_last_default_time on exit, the last time the ccache was default. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_change_time(): Get the last time a ccache was the default ccache. + * + * This function returns the last time when the ccache was made the default ccache. + * This allows clients to sort the ccaches by how recently they were default, which + * is useful for user listing of ccaches. If the ccache was never default, + * ccErrNeverDefault is returned. + */ + cc_int32 (*get_last_default_time) (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time); + + /*! + * \param in_ccache a cache object. + * \param out_change_time on exit, the last time the ccache changed. + * \return On success, #ccNoError. If the ccache was never the default ccache, + * #ccErrNeverDefault. Otherwise, an error code representing the failure. + * \brief \b cc_ccache_get_change_time(): Get the last time a ccache changed. + * + * This function returns the time of the most recent change made to a ccache. + * By maintaining a local copy the caller can deduce whether or not the ccache has + * been modified since the previous call to cc_ccache_get_change_time(). + * + * The time returned by cc_ccache_get_change_time() increases whenever: + * + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the ccache becomes the default ccache + * \li the ccache is no longer the default ccache + * + * \note In order to be able to compare two values returned by cc_ccache_get_change_time(), + * the caller must use the same ccache object to acquire them. Callers should maintain a + * single ccache object in memory for cc_ccache_get_change_time() calls rather than + * creating a new ccache object for every call. + * + * \sa wait_for_change + */ + cc_int32 (*get_change_time) (cc_ccache_t in_ccache, + cc_time_t *out_change_time); + + /*! + * \param in_ccache a ccache object. + * \param in_compare_to_ccache a ccache object to compare with \a in_ccache. + * \param out_equal on exit, whether or not the two ccaches refer to the same ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_compare(): Compare two ccache objects. + */ + cc_int32 (*compare) (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \param out_time_offset on exit, the KDC time offset for \a in_ccache for credentials version + * \a in_credentials_version. + * \return On success, #ccNoError if a time offset was obtained or #ccErrTimeOffsetNotSet + * if a time offset has not been set. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_kdc_time_offset(): Get the KDC time offset for credentials in a ccache. + * \sa set_kdc_time_offset, clear_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_get_kdc_time_offset() + * returns the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*get_kdc_time_offset) (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \param in_time_offset the new KDC time offset for \a in_ccache for credentials version + * \a in_credentials_version. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_kdc_time_offset(): Set the KDC time offset for credentials in a ccache. + * \sa get_kdc_time_offset, clear_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_set_kdc_time_offset() + * sets the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*set_kdc_time_offset) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_clear_kdc_time_offset(): Clear the KDC time offset for credentials in a ccache. + * \sa get_kdc_time_offset, set_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_clear_kdc_time_offset() + * clears the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*clear_kdc_time_offset) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version); + + /*! + * \param in_ccache a ccache object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_wait_for_change(): Wait for the next change to a ccache. + * + * This function blocks until the next change is made to the ccache referenced by + * \a in_ccache. By repeatedly calling cc_ccache_wait_for_change() from + * a worker thread the caller can effectively receive callbacks whenever the + * ccache changes. This is considerably more efficient than polling + * with cc_ccache_get_change_time(). + * + * cc_ccache_wait_for_change() will return whenever: + * + * \li a credential is stored + * \li a credential is removed + * \li the ccache principal is changed + * \li the ccache becomes the default ccache + * \li the ccache is no longer the default ccache + * + * \note In order to make sure that the caller doesn't miss any changes, + * cc_ccache_wait_for_change() always returns immediately after the first time it + * is called on a new ccache object. Callers must use the same ccache object + * for successive calls to cc_ccache_wait_for_change() rather than creating a new + * ccache object for every call. + * + * \sa get_change_time + */ + cc_int32 (*wait_for_change) (cc_ccache_t in_ccache); +}; + +/*! + * Function pointer table for cc_string_t. For more information see + * \ref cc_string_reference. + */ +struct cc_string_f { + /*! + * \param io_string the string object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_string_release(): Release memory associated with a cc_string_t object. + */ + cc_int32 (*release) (cc_string_t io_string); +}; + +/*! + * Function pointer table for cc_credentials_t. For more information see + * \ref cc_credentials_reference. + */ +struct cc_credentials_f { + /*! + * \param io_credentials the credentials object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_release(): Release memory associated with a cc_credentials_t object. + */ + cc_int32 (*release) (cc_credentials_t io_credentials); + + /*! + * \param in_credentials a credentials object. + * \param in_compare_to_credentials a credentials object to compare with \a in_credentials. + * \param out_equal on exit, whether or not the two credentials objects refer to the + * same credentials in the cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_compare(): Compare two credentials objects. + */ + cc_int32 (*compare) (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal); +}; + +/*! + * Function pointer table for cc_ccache_iterator_t. For more information see + * \ref cc_ccache_iterator_reference. + */ +struct cc_ccache_iterator_f { + /*! + * \param io_ccache_iterator the ccache iterator object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_release(): Release memory associated with a cc_ccache_iterator_t object. + */ + cc_int32 (*release) (cc_ccache_iterator_t io_ccache_iterator); + + /*! + * \param in_ccache_iterator a ccache iterator object. + * \param out_ccache on exit, the next ccache in the cache collection. + * \return On success, #ccNoError if the next ccache in the cache collection was + * obtained or #ccIteratorEnd if there are no more ccaches. + * On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_next(): Get the next ccache in the cache collection. + */ + cc_int32 (*next) (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache); + + /*! + * \param in_ccache_iterator a ccache iterator object. + * \param out_ccache_iterator on exit, a copy of \a in_ccache_iterator. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_clone(): Make a copy of a ccache iterator. + */ + cc_int32 (*clone) (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator); +}; + +/*! + * Function pointer table for cc_credentials_iterator_t. For more information see + * \ref cc_credentials_iterator_reference. + */ +struct cc_credentials_iterator_f { + /*! + * \param io_credentials_iterator the credentials iterator object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_release(): Release memory associated with a cc_credentials_iterator_t object. + */ + cc_int32 (*release) (cc_credentials_iterator_t io_credentials_iterator); + + /*! + * \param in_credentials_iterator a credentials iterator object. + * \param out_credentials on exit, the next credentials in the ccache. + * \return On success, #ccNoError if the next credential in the ccache was obtained + * or #ccIteratorEnd if there are no more credentials. + * On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_next(): Get the next credentials in the ccache. + */ + cc_int32 (*next) (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials); + + /*! + * \ingroup cc_credentials_iterator_reference + * \param in_credentials_iterator a credentials iterator object. + * \param out_credentials_iterator on exit, a copy of \a in_credentials_iterator. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_clone(): Make a copy of a credentials iterator. + */ + cc_int32 (*clone) (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator); +}; + +/*! + * \ingroup cc_context_reference + * \param out_context on exit, a new context object. Must be free with cc_context_release(). + * \param in_version the requested API version. This should be the maximum version the + * application supports. + * \param out_supported_version if non-NULL, on exit contains the maximum API version + * supported by the implementation. + * \param out_vendor if non-NULL, on exit contains a pointer to a read-only C string which + * contains a string describing the vendor which implemented the credentials cache API. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * May return CCAPI v2 error CC_BAD_API_VERSION if #ccapi_version_2 is passed in. + * \brief Initialize a new cc_context. + */ +CCACHE_API cc_int32 cc_initialize (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor); + + +/*! \defgroup helper_macros CCAPI Function Helper Macros + * @{ */ + +/*! Helper macro for cc_context_f release() */ +#define cc_context_release(context) \ + ((context) -> functions -> release (context)) +/*! Helper macro for cc_context_f get_change_time() */ +#define cc_context_get_change_time(context, change_time) \ + ((context) -> functions -> get_change_time (context, change_time)) +/*! Helper macro for cc_context_f get_default_ccache_name() */ +#define cc_context_get_default_ccache_name(context, name) \ + ((context) -> functions -> get_default_ccache_name (context, name)) +/*! Helper macro for cc_context_f open_ccache() */ +#define cc_context_open_ccache(context, name, ccache) \ + ((context) -> functions -> open_ccache (context, name, ccache)) +/*! Helper macro for cc_context_f open_default_ccache() */ +#define cc_context_open_default_ccache(context, ccache) \ + ((context) -> functions -> open_default_ccache (context, ccache)) +/*! Helper macro for cc_context_f create_ccache() */ +#define cc_context_create_ccache(context, name, version, principal, ccache) \ + ((context) -> functions -> create_ccache (context, name, version, principal, ccache)) +/*! Helper macro for cc_context_f create_default_ccache() */ +#define cc_context_create_default_ccache(context, version, principal, ccache) \ + ((context) -> functions -> create_default_ccache (context, version, principal, ccache)) +/*! Helper macro for cc_context_f create_new_ccache() */ +#define cc_context_create_new_ccache(context, version, principal, ccache) \ + ((context) -> functions -> create_new_ccache (context, version, principal, ccache)) +/*! Helper macro for cc_context_f new_ccache_iterator() */ +#define cc_context_new_ccache_iterator(context, iterator) \ + ((context) -> functions -> new_ccache_iterator (context, iterator)) +/*! Helper macro for cc_context_f lock() */ +#define cc_context_lock(context, type, block) \ + ((context) -> functions -> lock (context, type, block)) +/*! Helper macro for cc_context_f unlock() */ +#define cc_context_unlock(context) \ + ((context) -> functions -> unlock (context)) +/*! Helper macro for cc_context_f compare() */ +#define cc_context_compare(context, compare_to, equal) \ + ((context) -> functions -> compare (context, compare_to, equal)) +/*! Helper macro for cc_context_f wait_for_change() */ +#define cc_context_wait_for_change(context) \ + ((context) -> functions -> wait_for_change (context)) + +/*! Helper macro for cc_ccache_f release() */ +#define cc_ccache_release(ccache) \ + ((ccache) -> functions -> release (ccache)) +/*! Helper macro for cc_ccache_f destroy() */ +#define cc_ccache_destroy(ccache) \ + ((ccache) -> functions -> destroy (ccache)) +/*! Helper macro for cc_ccache_f set_default() */ +#define cc_ccache_set_default(ccache) \ + ((ccache) -> functions -> set_default (ccache)) +/*! Helper macro for cc_ccache_f get_credentials_version() */ +#define cc_ccache_get_credentials_version(ccache, version) \ + ((ccache) -> functions -> get_credentials_version (ccache, version)) +/*! Helper macro for cc_ccache_f get_name() */ +#define cc_ccache_get_name(ccache, name) \ + ((ccache) -> functions -> get_name (ccache, name)) +/*! Helper macro for cc_ccache_f get_principal() */ +#define cc_ccache_get_principal(ccache, version, principal) \ + ((ccache) -> functions -> get_principal (ccache, version, principal)) +/*! Helper macro for cc_ccache_f set_principal() */ +#define cc_ccache_set_principal(ccache, version, principal) \ + ((ccache) -> functions -> set_principal (ccache, version, principal)) +/*! Helper macro for cc_ccache_f store_credentials() */ +#define cc_ccache_store_credentials(ccache, credentials) \ + ((ccache) -> functions -> store_credentials (ccache, credentials)) +/*! Helper macro for cc_ccache_f remove_credentials() */ +#define cc_ccache_remove_credentials(ccache, credentials) \ + ((ccache) -> functions -> remove_credentials (ccache, credentials)) +/*! Helper macro for cc_ccache_f new_credentials_iterator() */ +#define cc_ccache_new_credentials_iterator(ccache, iterator) \ + ((ccache) -> functions -> new_credentials_iterator (ccache, iterator)) +/*! Helper macro for cc_ccache_f lock() */ +#define cc_ccache_lock(ccache, type, block) \ + ((ccache) -> functions -> lock (ccache, type, block)) +/*! Helper macro for cc_ccache_f unlock() */ +#define cc_ccache_unlock(ccache) \ + ((ccache) -> functions -> unlock (ccache)) +/*! Helper macro for cc_ccache_f get_last_default_time() */ +#define cc_ccache_get_last_default_time(ccache, last_default_time) \ + ((ccache) -> functions -> get_last_default_time (ccache, last_default_time)) +/*! Helper macro for cc_ccache_f get_change_time() */ +#define cc_ccache_get_change_time(ccache, change_time) \ + ((ccache) -> functions -> get_change_time (ccache, change_time)) +/*! Helper macro for cc_ccache_f move() */ +#define cc_ccache_move(source, destination) \ + ((source) -> functions -> move (source, destination)) +/*! Helper macro for cc_ccache_f compare() */ +#define cc_ccache_compare(ccache, compare_to, equal) \ + ((ccache) -> functions -> compare (ccache, compare_to, equal)) +/*! Helper macro for cc_ccache_f get_kdc_time_offset() */ +#define cc_ccache_get_kdc_time_offset(ccache, version, time_offset) \ + ((ccache) -> functions -> get_kdc_time_offset (ccache, version, time_offset)) +/*! Helper macro for cc_ccache_f set_kdc_time_offset() */ +#define cc_ccache_set_kdc_time_offset(ccache, version, time_offset) \ + ((ccache) -> functions -> set_kdc_time_offset (ccache, version, time_offset)) +/*! Helper macro for cc_ccache_f clear_kdc_time_offset() */ +#define cc_ccache_clear_kdc_time_offset(ccache, version) \ + ((ccache) -> functions -> clear_kdc_time_offset (ccache, version)) +/*! Helper macro for cc_ccache_f wait_for_change() */ +#define cc_ccache_wait_for_change(ccache) \ + ((ccache) -> functions -> wait_for_change (ccache)) + +/*! Helper macro for cc_string_f release() */ +#define cc_string_release(string) \ + ((string) -> functions -> release (string)) + +/*! Helper macro for cc_credentials_f release() */ +#define cc_credentials_release(credentials) \ + ((credentials) -> functions -> release (credentials)) +/*! Helper macro for cc_credentials_f compare() */ +#define cc_credentials_compare(credentials, compare_to, equal) \ + ((credentials) -> functions -> compare (credentials, compare_to, equal)) + +/*! Helper macro for cc_ccache_iterator_f release() */ +#define cc_ccache_iterator_release(iterator) \ + ((iterator) -> functions -> release (iterator)) +/*! Helper macro for cc_ccache_iterator_f next() */ +#define cc_ccache_iterator_next(iterator, ccache) \ + ((iterator) -> functions -> next (iterator, ccache)) +/*! Helper macro for cc_ccache_iterator_f clone() */ +#define cc_ccache_iterator_clone(iterator, new_iterator) \ + ((iterator) -> functions -> clone (iterator, new_iterator)) + +/*! Helper macro for cc_credentials_iterator_f release() */ +#define cc_credentials_iterator_release(iterator) \ + ((iterator) -> functions -> release (iterator)) +/*! Helper macro for cc_credentials_iterator_f next() */ +#define cc_credentials_iterator_next(iterator, credentials) \ + ((iterator) -> functions -> next (iterator, credentials)) +/*! Helper macro for cc_credentials_iterator_f clone() */ +#define cc_credentials_iterator_clone(iterator, new_iterator) \ + ((iterator) -> functions -> clone (iterator, new_iterator)) +/*!@}*/ + +#if TARGET_OS_MAC +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CREDENTIALSCACHE__ */ diff --git a/krb5-1-7/src/include/CredentialsCache2.h b/krb5-1-7/src/include/CredentialsCache2.h new file mode 100644 index 000000000..b0c45d59e --- /dev/null +++ b/krb5-1-7/src/include/CredentialsCache2.h @@ -0,0 +1,326 @@ +/* + * $Header$ + * + * 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 backwards compatibility for CCache API v2 clients to be able to run + * against the CCache API v3 library + */ + +#ifndef CCAPI_V2_H +#define CCAPI_V2_H + +#include + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#include +#ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER +#define CCAPI_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER +#endif +#endif + +#ifndef CCAPI_DEPRECATED +#define CCAPI_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if TARGET_OS_MAC +#pragma pack(push,2) +#endif + +/* Some old types get directly mapped to new types */ + +typedef cc_context_d apiCB; +typedef cc_ccache_d ccache_p; +typedef cc_credentials_iterator_d ccache_cit_creds; +typedef cc_ccache_iterator_d ccache_cit_ccache; +typedef cc_data cc_data_compat; +typedef cc_int32 cc_cred_vers; +typedef cc_int32 cc_result; + +/* This doesn't exist in API v3 */ +typedef cc_uint32 cc_flags; + +/* Credentials types are visible to the caller so we have to keep binary compatibility */ + +typedef struct cc_credentials_v5_compat { + char* client; + char* server; + cc_data_compat 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_compat** addresses; + cc_data_compat ticket; + cc_data_compat second_ticket; + cc_data_compat** authdata; +} cc_credentials_v5_compat; + +enum { + MAX_V4_CRED_LEN = 1250 +}; + +enum { + KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40 +}; + +typedef struct cc_credentials_v4_compat { + 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; + cc_int32 str_to_key; + long issue_date; + cc_int32 lifetime; + cc_uint32 address; + cc_int32 ticket_sz; + unsigned char ticket[MAX_V4_CRED_LEN]; + unsigned long oops; +} cc_credentials_v4_compat; + +typedef union cred_ptr_union_compat { + cc_credentials_v4_compat* pV4Cred; + cc_credentials_v5_compat* pV5Cred; +} cred_ptr_union_compat; + +typedef struct cred_union { + cc_int32 cred_type; /* cc_cred_vers */ + cred_ptr_union_compat cred; +} cred_union; + +/* NC info structure is gone in v3 */ + +struct infoNC { + char* name; + char* principal; + cc_int32 vers; +}; + +typedef struct infoNC infoNC; + +/* Some old type names */ + +typedef cc_credentials_v4_compat V4Cred_type; +typedef cc_credentials_v5_compat cc_creds; +struct ccache_cit; +typedef struct ccache_cit ccache_cit; + +enum { + CC_API_VER_2 = ccapi_version_2 +}; + +enum { + CC_NOERROR, + CC_BADNAME, + CC_NOTFOUND, + CC_END, + CC_IO, + CC_WRITE, + CC_NOMEM, + CC_FORMAT, + CC_LOCKED, + CC_BAD_API_VERSION, + CC_NO_EXIST, + CC_NOT_SUPP, + CC_BAD_PARM, + CC_ERR_CACHE_ATTACH, + CC_ERR_CACHE_RELEASE, + CC_ERR_CACHE_FULL, + CC_ERR_CRED_VERSION +}; + +enum { + CC_CRED_UNKNOWN, + CC_CRED_V4, + CC_CRED_V5, + CC_CRED_MAX +}; + +enum { + CC_LOCK_UNLOCK = 1, + CC_LOCK_READER = 2, + CC_LOCK_WRITER = 3, + CC_LOCK_NOBLOCK = 16 +}; + +CCACHE_API cc_int32 +cc_shutdown (apiCB **io_context) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_NC_info (apiCB *in_context, + infoNC ***out_info) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_change_time (apiCB *in_context, + cc_time_t *out_change_time) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_open (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_create (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_close (apiCB *in_context, + ccache_p **ioCCache) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_destroy (apiCB *in_context, + ccache_p **io_ccache) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_begin (apiCB *in_context, + ccache_cit **out_nc_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_next (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_nc_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_end (apiCB *in_context, + ccache_cit **io_nc_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_name (apiCB *in_context, + ccache_p *in_ccache, + char **out_name) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_cred_version (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_set_principal (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 in_version, + char *in_principal) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_principal (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_store (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_remove_cred (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_begin (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_ccache_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_next (apiCB *in_context, + cred_union **out_cred_union, + ccache_cit *in_ccache_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_end (apiCB *in_context, + ccache_cit **io_ccache_iterator) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_principal (apiCB *in_context, + char **io_principal) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_name (apiCB *in_context, + char **io_name) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_creds (apiCB *in_context, + cred_union **io_cred_union) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_NC_info (apiCB *in_context, + infoNC ***io_info) +CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_lock_request (apiCB *in_context, + const ccache_p *in_ccache, + const cc_int32 in_lock_type) +CCAPI_DEPRECATED; + +#if TARGET_OS_MAC +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CCAPI_V2_H */ diff --git a/krb5-1-7/src/include/Makefile.in b/krb5-1-7/src/include/Makefile.in new file mode 100644 index 000000000..2b7cc0877 --- /dev/null +++ b/krb5-1-7/src/include/Makefile.in @@ -0,0 +1,139 @@ +thisconfigdir=.. +myfulldir=include +mydir=include +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 +K5_ET_HEADERS = \ + ../lib/krb5/error_tables/krb5_err.h \ + ../lib/krb5/error_tables/kdb5_err.h \ + ../lib/krb5/error_tables/kv5m_err.h \ + ../lib/krb5/error_tables/krb524_err.h \ + ../lib/krb5/error_tables/asn1_err.h +BUILT_HEADERS = osconf.h + +all-unix:: autoconf.h $(BUILT_HEADERS) +all-windows:: autoconf.h $(BUILT_HEADERS) verify-calling-conventions-krb5 + +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: osconf.hin +##DOS## $(CP) osconf.hin $@ + +############################################################################### +##DOS##!if 0 +# config.status will now update autoconf.stamp itself. +autoconf.h: autoconf.stamp +autoconf.stamp: $(srcdir)/autoconf.h.in $(thisconfigdir)/config.status + (cd $(thisconfigdir) && $(SHELL) config.status $(mydir)/autoconf.h) + +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+@GSSMODULEDIR+$(GSS_MODULE_DIR)+" \ + -e 's+@LOCALSTATEDIR+$(LOCALSTATEDIR)+' \ + -e 's+@SYSCONFDIR+$(SYSCONFDIR)+' + +OSCONFSRC = $(srcdir)/osconf.hin + +osconf.h: $(OSCONFSRC) Makefile + cat $(OSCONFSRC) | sed $(PROCESS_REPLACE) > osconf.new + $(MOVEIFCHANGED) osconf.new osconf.h +##DOS##!endif +############################################################################### + +krb5/krb5.h: krb5.stamp; : krb5.h +krb5.stamp: $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS) + 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.new + echo "#ifndef KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new + echo "#define KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new + cat $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS) >> krb5/krb5.new + echo "#endif /* KRB5_KRB5_H_INCLUDED */" >> krb5/krb5.new + $(MOVEIFCHANGED) krb5/krb5.new krb5/krb5.h + touch krb5.stamp + +verify-calling-conventions-krb5: private-and-public-decls + $(PERL) -w $(SRCTOP)/util/def-check.pl private-and-public-decls $(SRCTOP)/lib/krb5_32.def + +##DOS##!if 0 +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) > $@ +##DOS##!endif +##DOS##private-and-public-decls: +##DOS## copy krb5\krb5.h+k5-int.h+krb5\preauth_plugin.h $@ + +# +# Build the error table include files: +# asn1_err.h kdb5_err.h krb5_err.h kv5m_err.h krb524_err.h + +$(K5_ET_HEADERS): rebuild-error-tables + : $@ +rebuild-error-tables: + (cd ../lib/krb5/error_tables && $(MAKE) includes) + +.PHONY: force rebuild-error-tables +force: + +clean-unix:: + $(RM) krb5/krb5.h krb5_err.h kdb5_err.h kv5m_err.h krb524_err.h \ + asn1_err.h private-and-public-decls krb5.stamp + $(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) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.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-7/src/include/adm.h b/krb5-1-7/src/include/adm.h new file mode 100644 index 000000000..15b42d9ab --- /dev/null +++ b/krb5-1-7/src/include/adm.h @@ -0,0 +1,222 @@ +/* + * include/krb5/adm.h + * + * Copyright 1995,2001,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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; + char * realm_host_based_services; + char * realm_no_host_referral; + 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-7/src/include/adm_proto.h b/krb5-1-7/src/include/adm_proto.h new file mode 100644 index 000000000..47d500d0d --- /dev/null +++ b/krb5-1-7/src/include/adm_proto.h @@ -0,0 +1,139 @@ +/* + * include/krb5/adm_proto.h + * + * Copyright 1995, 2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; +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_string_all + (krb5_pointer, const char **, 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 *); +krb5_boolean krb5_match_config_pattern(const char *, const char *); + +/* 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-7/src/include/cm.h b/krb5-1-7/src/include/cm.h new file mode 100644 index 000000000..716e6cb59 --- /dev/null +++ b/krb5-1-7/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-7/src/include/copyright.h b/krb5-1-7/src/include/copyright.h new file mode 100644 index 000000000..b1740ce3c --- /dev/null +++ b/krb5-1-7/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-7/src/include/deps b/krb5-1-7/src/include/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/include/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/include/fake-addrinfo.h b/krb5-1-7/src/include/fake-addrinfo.h new file mode 100644 index 000000000..952b43f0b --- /dev/null +++ b/krb5-1-7/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-7/src/include/foreachaddr.h b/krb5-1-7/src/include/foreachaddr.h new file mode 100644 index 000000000..57591f596 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssapi.h b/krb5-1-7/src/include/gssapi.h new file mode 100644 index 000000000..f55768144 --- /dev/null +++ b/krb5-1-7/src/include/gssapi.h @@ -0,0 +1,5 @@ +/* + * Wrapper so that #include will work without special include + * paths. + */ +#include diff --git a/krb5-1-7/src/include/gssrpc/auth.h b/krb5-1-7/src/include/gssrpc/auth.h new file mode 100644 index 000000000..cc3de9764 --- /dev/null +++ b/krb5-1-7/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__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-7/src/include/gssrpc/auth_gss.h b/krb5-1-7/src/include/gssrpc/auth_gss.h new file mode 100644 index 000000000..ea5db92b9 --- /dev/null +++ b/krb5-1-7/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 . + 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 +#include +#ifdef HAVE_HEIMDAL +#include +#else +#include +#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-7/src/include/gssrpc/auth_gssapi.h b/krb5-1-7/src/include/gssrpc/auth_gssapi.h new file mode 100644 index 000000000..73a2f0b16 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/auth_unix.h b/krb5-1-7/src/include/gssrpc/auth_unix.h new file mode 100644 index 000000000..9be442278 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/clnt.h b/krb5-1-7/src/include/gssrpc/clnt.h new file mode 100644 index 000000000..95450a241 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/netdb.h b/krb5-1-7/src/include/gssrpc/netdb.h new file mode 100644 index 000000000..69267874e --- /dev/null +++ b/krb5-1-7/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 +/* 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 are) --marc */ + +/* Really belongs in */ +#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-7/src/include/gssrpc/pmap_clnt.h b/krb5-1-7/src/include/gssrpc/pmap_clnt.h new file mode 100644 index 000000000..808306865 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/pmap_prot.h b/krb5-1-7/src/include/gssrpc/pmap_prot.h new file mode 100644 index 000000000..8a8802b05 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/pmap_rmt.h b/krb5-1-7/src/include/gssrpc/pmap_rmt.h new file mode 100644 index 000000000..48789b453 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/rename.h b/krb5-1-7/src/include/gssrpc/rename.h new file mode 100644 index 000000000..6e472e617 --- /dev/null +++ b/krb5-1-7/src/include/gssrpc/rename.h @@ -0,0 +1,309 @@ +/* + * 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 and might get ours instead. + * OS vendors should replace all the inclusions with + * 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_sizeof gssrpc_xdr_sizeof + +#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-7/src/include/gssrpc/rpc.h b/krb5-1-7/src/include/gssrpc/rpc.h new file mode 100644 index 000000000..0f1730d18 --- /dev/null +++ b/krb5-1-7/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 /* some typedefs */ +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +#include /* protocol for unix style cred */ +#include /* 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 protocol for des style cred +#endif + +/* Server side only remote procedure callee */ +#include /* service side authenticator */ +#include /* 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 included in . + */ +/* routines for parsing /etc/rpc */ +#if 0 /* netdb.h already included in rpc/types.h */ +#include +#endif + +#include /* 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-7/src/include/gssrpc/rpc_msg.h b/krb5-1-7/src/include/gssrpc/rpc_msg.h new file mode 100644 index 000000000..62d632967 --- /dev/null +++ b/krb5-1-7/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-7/src/include/gssrpc/svc.h b/krb5-1-7/src/include/gssrpc/svc.h new file mode 100644 index 000000000..dfe0bec65 --- /dev/null +++ b/krb5-1-7/src/include/gssrpc/svc.h @@ -0,0 +1,341 @@ +/* @(#)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__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 { +#ifdef _WIN32 + SOCKET xp_sock; +#else + int xp_sock; +#endif + 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 IPPROTO_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-7/src/include/gssrpc/svc_auth.h b/krb5-1-7/src/include/gssrpc/svc_auth.h new file mode 100644 index 000000000..541aa4514 --- /dev/null +++ b/krb5-1-7/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 + +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-7/src/include/gssrpc/types.hin b/krb5-1-7/src/include/gssrpc/types.hin new file mode 100644 index 000000000..ed612f1f5 --- /dev/null +++ b/krb5-1-7/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 + */ +#ifndef GSSRPC_TYPES_H +#define GSSRPC_TYPES_H + +#include + +@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 + +#include + +/* + * 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 + +#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 /* 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 + +#endif /* !defined(GSSRPC_TYPES_H) */ diff --git a/krb5-1-7/src/include/gssrpc/xdr.h b/krb5-1-7/src/include/gssrpc/xdr.h new file mode 100644 index 000000000..b7c2843a4 --- /dev/null +++ b/krb5-1-7/src/include/gssrpc/xdr.h @@ -0,0 +1,336 @@ +/* @(#)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 /* 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; + * *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 **); + +extern unsigned long xdr_sizeof(xdrproc_t, void *); + +#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-7/src/include/iprop.h b/krb5-1-7/src/include/iprop.h new file mode 100644 index 000000000..208f4dce0 --- /dev/null +++ b/krb5-1-7/src/include/iprop.h @@ -0,0 +1,269 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _IPROP_H_RPCGEN +#define _IPROP_H_RPCGEN + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u_int utf8str_t_len; + char *utf8str_t_val; +} utf8str_t; + +typedef uint32_t kdb_sno_t; + +struct kdbe_time_t { + uint32_t seconds; + uint32_t useconds; +}; +typedef struct kdbe_time_t kdbe_time_t; + +struct kdbe_key_t { + int32_t k_ver; + int32_t k_kvno; + struct { + u_int k_enctype_len; + int32_t *k_enctype_val; + } k_enctype; + struct { + u_int k_contents_len; + utf8str_t *k_contents_val; + } k_contents; +}; +typedef struct kdbe_key_t kdbe_key_t; + +struct kdbe_data_t { + int32_t k_magic; + utf8str_t k_data; +}; +typedef struct kdbe_data_t kdbe_data_t; + +struct kdbe_princ_t { + utf8str_t k_realm; + struct { + u_int k_components_len; + kdbe_data_t *k_components_val; + } k_components; + int32_t k_nametype; +}; +typedef struct kdbe_princ_t kdbe_princ_t; + +struct kdbe_tl_t { + int16_t tl_type; + struct { + u_int tl_data_len; + char *tl_data_val; + } tl_data; +}; +typedef struct kdbe_tl_t kdbe_tl_t; + +typedef struct { + u_int kdbe_pw_hist_t_len; + kdbe_key_t *kdbe_pw_hist_t_val; +} kdbe_pw_hist_t; + +enum kdbe_attr_type_t { + AT_ATTRFLAGS = 0, + AT_MAX_LIFE = 1, + AT_MAX_RENEW_LIFE = 2, + AT_EXP = 3, + AT_PW_EXP = 4, + AT_LAST_SUCCESS = 5, + AT_LAST_FAILED = 6, + AT_FAIL_AUTH_COUNT = 7, + AT_PRINC = 8, + AT_KEYDATA = 9, + AT_TL_DATA = 10, + AT_LEN = 11, + AT_MOD_PRINC = 12, + AT_MOD_TIME = 13, + AT_MOD_WHERE = 14, + AT_PW_LAST_CHANGE = 15, + AT_PW_POLICY = 16, + AT_PW_POLICY_SWITCH = 17, + AT_PW_HIST_KVNO = 18, + AT_PW_HIST = 19, +}; +typedef enum kdbe_attr_type_t kdbe_attr_type_t; + +struct kdbe_val_t { + kdbe_attr_type_t av_type; + union { + uint32_t av_attrflags; + uint32_t av_max_life; + uint32_t av_max_renew_life; + uint32_t av_exp; + uint32_t av_pw_exp; + uint32_t av_last_success; + uint32_t av_last_failed; + uint32_t av_fail_auth_count; + kdbe_princ_t av_princ; + struct { + u_int av_keydata_len; + kdbe_key_t *av_keydata_val; + } av_keydata; + struct { + u_int av_tldata_len; + kdbe_tl_t *av_tldata_val; + } av_tldata; + int16_t av_len; + uint32_t av_pw_last_change; + kdbe_princ_t av_mod_princ; + uint32_t av_mod_time; + utf8str_t av_mod_where; + utf8str_t av_pw_policy; + bool_t av_pw_policy_switch; + uint32_t av_pw_hist_kvno; + struct { + u_int av_pw_hist_len; + kdbe_pw_hist_t *av_pw_hist_val; + } av_pw_hist; + struct { + u_int av_extension_len; + char *av_extension_val; + } av_extension; + } kdbe_val_t_u; +}; +typedef struct kdbe_val_t kdbe_val_t; + +typedef struct { + u_int kdbe_t_len; + kdbe_val_t *kdbe_t_val; +} kdbe_t; + +struct kdb_incr_update_t { + utf8str_t kdb_princ_name; + kdb_sno_t kdb_entry_sno; + kdbe_time_t kdb_time; + kdbe_t kdb_update; + bool_t kdb_deleted; + bool_t kdb_commit; + struct { + u_int kdb_kdcs_seen_by_len; + utf8str_t *kdb_kdcs_seen_by_val; + } kdb_kdcs_seen_by; + struct { + u_int kdb_futures_len; + char *kdb_futures_val; + } kdb_futures; +}; +typedef struct kdb_incr_update_t kdb_incr_update_t; + +typedef struct { + u_int kdb_ulog_t_len; + kdb_incr_update_t *kdb_ulog_t_val; +} kdb_ulog_t; + +enum update_status_t { + UPDATE_OK = 0, + UPDATE_ERROR = 1, + UPDATE_FULL_RESYNC_NEEDED = 2, + UPDATE_BUSY = 3, + UPDATE_NIL = 4, + UPDATE_PERM_DENIED = 5, +}; +typedef enum update_status_t update_status_t; + +struct kdb_last_t { + kdb_sno_t last_sno; + kdbe_time_t last_time; +}; +typedef struct kdb_last_t kdb_last_t; + +struct kdb_incr_result_t { + kdb_last_t lastentry; + kdb_ulog_t updates; + update_status_t ret; +}; +typedef struct kdb_incr_result_t kdb_incr_result_t; + +struct kdb_fullresync_result_t { + kdb_last_t lastentry; + update_status_t ret; +}; +typedef struct kdb_fullresync_result_t kdb_fullresync_result_t; + +#define KRB5_IPROP_PROG 100423 +#define KRB5_IPROP_VERS 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define IPROP_NULL 0 +extern void * iprop_null_1(void *, CLIENT *); +extern void * iprop_null_1_svc(void *, struct svc_req *); +#define IPROP_GET_UPDATES 1 +extern kdb_incr_result_t * iprop_get_updates_1(kdb_last_t *, CLIENT *); +extern kdb_incr_result_t * iprop_get_updates_1_svc(kdb_last_t *, struct svc_req *); +#define IPROP_FULL_RESYNC 2 +extern kdb_fullresync_result_t * iprop_full_resync_1(void *, CLIENT *); +extern kdb_fullresync_result_t * iprop_full_resync_1_svc(void *, struct svc_req *); +extern int krb5_iprop_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define IPROP_NULL 0 +extern void * iprop_null_1(); +extern void * iprop_null_1_svc(); +#define IPROP_GET_UPDATES 1 +extern kdb_incr_result_t * iprop_get_updates_1(); +extern kdb_incr_result_t * iprop_get_updates_1_svc(); +#define IPROP_FULL_RESYNC 2 +extern kdb_fullresync_result_t * iprop_full_resync_1(); +extern kdb_fullresync_result_t * iprop_full_resync_1_svc(); +extern int krb5_iprop_prog_1_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_utf8str_t (XDR *, utf8str_t*); +extern bool_t xdr_kdb_sno_t (XDR *, kdb_sno_t*); +extern bool_t xdr_kdbe_time_t (XDR *, kdbe_time_t*); +extern bool_t xdr_kdbe_key_t (XDR *, kdbe_key_t*); +extern bool_t xdr_kdbe_data_t (XDR *, kdbe_data_t*); +extern bool_t xdr_kdbe_princ_t (XDR *, kdbe_princ_t*); +extern bool_t xdr_kdbe_tl_t (XDR *, kdbe_tl_t*); +extern bool_t xdr_kdbe_pw_hist_t (XDR *, kdbe_pw_hist_t*); +extern bool_t xdr_kdbe_attr_type_t (XDR *, kdbe_attr_type_t*); +extern bool_t xdr_kdbe_val_t (XDR *, kdbe_val_t*); +extern bool_t xdr_kdbe_t (XDR *, kdbe_t*); +extern bool_t xdr_kdb_incr_update_t (XDR *, kdb_incr_update_t*); +extern bool_t xdr_kdb_ulog_t (XDR *, kdb_ulog_t*); +extern bool_t xdr_update_status_t (XDR *, update_status_t*); +extern bool_t xdr_kdb_last_t (XDR *, kdb_last_t*); +extern bool_t xdr_kdb_incr_result_t (XDR *, kdb_incr_result_t*); +extern bool_t xdr_kdb_fullresync_result_t (XDR *, kdb_fullresync_result_t*); + +#else /* K&R C */ +extern bool_t xdr_utf8str_t (); +extern bool_t xdr_kdb_sno_t (); +extern bool_t xdr_kdbe_time_t (); +extern bool_t xdr_kdbe_key_t (); +extern bool_t xdr_kdbe_data_t (); +extern bool_t xdr_kdbe_princ_t (); +extern bool_t xdr_kdbe_tl_t (); +extern bool_t xdr_kdbe_pw_hist_t (); +extern bool_t xdr_kdbe_attr_type_t (); +extern bool_t xdr_kdbe_val_t (); +extern bool_t xdr_kdbe_t (); +extern bool_t xdr_kdb_incr_update_t (); +extern bool_t xdr_kdb_ulog_t (); +extern bool_t xdr_update_status_t (); +extern bool_t xdr_kdb_last_t (); +extern bool_t xdr_kdb_incr_result_t (); +extern bool_t xdr_kdb_fullresync_result_t (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_IPROP_H_RPCGEN */ diff --git a/krb5-1-7/src/include/iprop_hdr.h b/krb5-1-7/src/include/iprop_hdr.h new file mode 100644 index 000000000..d629542bb --- /dev/null +++ b/krb5-1-7/src/include/iprop_hdr.h @@ -0,0 +1,42 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#ifndef _IPROP_HDR_H +#define _IPROP_HDR_H + +/* #pragma ident "@(#)iprop_hdr.h 1.1 04/02/20 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file has some defines common to the iprop client and + * server routines. + */ + +/* + * Maximum size for each ulog entry is 2KB and maximum + * possible attribute-value pairs for each ulog entry is 20 + */ +#define MAXENTRY_SIZE 2048 +#define MAXATTRS_SIZE 20 + +#define KIPROP_SVC_NAME "kiprop" +#define MAX_BACKOFF 300 /* Backoff for a maximum for 5 mts */ + +enum iprop_role { + IPROP_NULL = 0, + IPROP_MASTER = 1, + IPROP_SLAVE = 2 +}; +typedef enum iprop_role iprop_role; + +#ifdef __cplusplus +} +#endif + +#endif /* !_IPROP_HDR_H */ diff --git a/krb5-1-7/src/include/k5-buf.h b/krb5-1-7/src/include/k5-buf.h new file mode 100644 index 000000000..4f7a939a9 --- /dev/null +++ b/krb5-1-7/src/include/k5-buf.h @@ -0,0 +1,125 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * include/k5-buf.h + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * k5buf string buffer module interface + */ + +#ifndef K5_BUF_H +#define K5_BUF_H + +#if defined(_MSDOS) || defined(_WIN32) +#include +#endif +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include +#include +#include + +/* The k5buf module is intended to allow multi-step string + construction in a fixed or dynamic buffer without the need to check + for a failure at each step (and without aborting on malloc + failure). If an allocation failure occurs or if the fixed buffer + runs out of room, the error will be discovered when the caller + retrieves the C string value or checks the length of the resulting + buffer. + + k5buf structures are stack-allocated, but are intended to be + opaque, so do not access the fields directly. This is a tool, not + a way of life, so do not put k5buf structure pointers into the + public API or into significant internal APIs. */ + +/* We must define the k5buf structure here to allow stack allocation. + The structure is intended to be opaque, so the fields have funny + names. */ +struct k5buf { + int xx_buftype; + char *xx_data; + size_t xx_space; + size_t xx_len; +}; + +/* Initialize a k5buf using a fixed-sized, existing buffer. SPACE + must be more than zero, or an assertion failure will result. */ +void krb5int_buf_init_fixed(struct k5buf *buf, char *data, size_t space); + +/* Initialize a k5buf using an internally allocated dynamic buffer. + The buffer contents must be freed with krb5int_free_buf. */ +void krb5int_buf_init_dynamic(struct k5buf *buf); + +/* Add a C string to BUF. */ +void krb5int_buf_add(struct k5buf *buf, const char *data); + +/* Add a counted set of bytes to BUF. If is okay for DATA[0..LEN-1] + to contain null bytes if you are prepared to deal with that in the + output (use krb5int_buf_len to retrieve the length of the output). */ +void krb5int_buf_add_len(struct k5buf *buf, const char *data, size_t len); + +/* Add sprintf-style formatted data to BUF. */ +void krb5int_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +/* Truncate BUF. LEN must be between 0 and the existing buffer + length, or an assertion failure will result. */ +void krb5int_buf_truncate(struct k5buf *buf, size_t len); + +/* Retrieve the byte array value of BUF, or NULL if there has been an + allocation failure or the fixed buffer ran out of room. + + The byte array will be a C string unless binary data was added with + krb5int_buf_add_len; it will be null-terminated regardless. + Modifying the byte array does not invalidate the buffer, as long as + its length is not changed. + + For a fixed buffer, the return value will always be equal to the + passed-in value of DATA at initialization time if it is not NULL. + + For a dynamic buffer, any buffer modification operation except + krb5int_buf_truncate may invalidate the byte array address. */ +char *krb5int_buf_data(struct k5buf *buf); + +/* Retrieve the length of BUF, or -1 if there has been an allocation + failure or the fixed buffer ran out of room. The length is equal + to strlen(krb5int_buf_data(buf)) unless binary data was added with + krb5int_buf_add_len. */ +ssize_t krb5int_buf_len(struct k5buf *buf); + +/* Free the storage used in the dynamic buffer BUF. The caller may + choose to take responsibility for freeing the return value of + krb5int_buf_data instead of using this function. If BUF is a fixed + buffer, an assertion failure will result. It is unnecessary + (though harmless) to free a buffer after an error is detected; the + storage will already have been freed in that case. */ +void krb5int_free_buf(struct k5buf *buf); + +#endif /* K5_BUF_H */ diff --git a/krb5-1-7/src/include/k5-err.h b/krb5-1-7/src/include/k5-err.h new file mode 100644 index 000000000..e5fc9bddf --- /dev/null +++ b/krb5-1-7/src/include/k5-err.h @@ -0,0 +1,98 @@ +/* + * include/k5-err.h + * + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#endif +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include + +struct errinfo { + long code; + const char *msg; + char scratch_buf[1024]; +}; + +void +krb5int_set_error (struct errinfo *ep, + long code, + const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; +void +krb5int_vset_error (struct errinfo *ep, long code, + const char *fmt, va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; +void +krb5int_set_error_fl (struct errinfo *ep, long code, + const char *file, int line, + const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 5, 6))) +#endif + ; +void +krb5int_vset_error_fl (struct errinfo *ep, long code, + const char *file, int line, + const char *fmt, va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 5, 0))) +#endif + ; +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)); + +#ifdef DEBUG_ERROR_LOCATIONS +#define krb5int_set_error(ep, code, ...) \ + krb5int_set_error_fl(ep, code, __FILE__, __LINE__, __VA_ARGS__) +#endif + +#endif /* K5_ERR_H */ diff --git a/krb5-1-7/src/include/k5-gmt_mktime.h b/krb5-1-7/src/include/k5-gmt_mktime.h new file mode 100644 index 000000000..d9d1d1e5a --- /dev/null +++ b/krb5-1-7/src/include/k5-gmt_mktime.h @@ -0,0 +1,51 @@ +/* + * include/k5-gmt_mktime.h + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * GMT struct tm conversion + * + * Because of ordering of things in the UNIX build, we can't just keep + * the declaration in k5-int.h and include it in + * util/support/gmt_mktime.c, since k5-int.h includes krb5.h which + * hasn't been built when gmt_mktime.c gets compiled. Hence this + * silly little helper header. + */ + +#ifndef K5_GMT_MKTIME_H +#define K5_GMT_MKTIME_H + +#include "autoconf.h" +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#include +#endif + +time_t krb5int_gmt_mktime (struct tm *); + +#endif /* K5_GMT_MKTIME_H */ diff --git a/krb5-1-7/src/include/k5-int-pkinit.h b/krb5-1-7/src/include/k5-int-pkinit.h new file mode 100644 index 000000000..2fb5f8719 --- /dev/null +++ b/krb5-1-7/src/include/k5-int-pkinit.h @@ -0,0 +1,275 @@ +/* + * 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 */ +/* The FAST error handling logic currently assumes that this structure and krb5_pa_data * can be safely cast to each other + * if this structure changes, that code needs to be updated to copy. + */ +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 ***); + +void krb5_free_typed_data(krb5_context, krb5_typed_data **); + +#endif /* _KRB5_INT_PKINIT_H */ diff --git a/krb5-1-7/src/include/k5-int.h b/krb5-1-7/src/include/k5-int.h new file mode 100644 index 000000000..2002f42a8 --- /dev/null +++ b/krb5-1-7/src/include/k5-int.h @@ -0,0 +1,2836 @@ +/* + * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2007,2008,2009 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" + +#if defined(__MACH__) && defined(__APPLE__) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +/* + * 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 + +#include "autoconf.h" + +#ifndef KRB5_SYSTYPES__ +#define KRB5_SYSTYPES__ + +#ifdef HAVE_SYS_TYPES_H /* From autoconf.h */ +#include +#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 +#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" + +/* Get string buffer support. */ +#include "k5-buf.h" + +/* cofiguration variables */ +#define KRB5_CONF_ACL_FILE "acl_file" +#define KRB5_CONF_ADMIN_KEYTAB "admin_keytab" +#define KRB5_CONF_ADMIN_SERVER "admin_server" +#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto" +#define KRB5_CONF_AP_REQ_CHECKSUM_TYPE "ap_req_checksum_type" +#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local" +#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names" +#define KRB5_CONF_CANONICALIZE "canonicalize" +#define KRB5_CONF_CCACHE_TYPE "ccache_type" +#define KRB5_CONF_CLOCKSKEW "clockskew" +#define KRB5_CONF_DATABASE_NAME "database_name" +#define KRB5_CONF_DB_MODULE_DIR "db_module_dir" +#define KRB5_CONF_DB_MODULES "db_modules" +#define KRB5_CONF_DOMAIN_REALM "domain_realm" +#define KRB5_CONF_DEFAULT_REALM "default_realm" +#define KRB5_CONF_DEFAULT_DOMAIN "default_domain" +#define KRB5_CONF_DEFAULT_TKT_ENCTYPES "default_tkt_enctypes" +#define KRB5_CONF_DEFAULT_TGS_ENCTYPES "default_tgs_enctypes" +#define KRB5_CONF_DEFAULT_KEYTAB_NAME "default_keytab_name" +#define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration" +#define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS "default_principal_flags" +#define KRB5_CONF_DICT_FILE "dict_file" +#define KRB5_CONF_DNS_LOOKUP_KDC "dns_lookup_kdc" +#define KRB5_CONF_DNS_LOOKUP_REALM "dns_lookup_realm" +#define KRB5_CONF_DNS_FALLBACK "dns_fallback" +#define KRB5_CONF_EXTRA_ADDRESSES "extra_addresses" +#define KRB5_CONF_FORWARDABLE "forwardable" +#define KRB5_CONF_HOST_BASED_SERVICES "host_based_services" +#define KRB5_CONF_IPROP_ENABLE "iprop_enable" +#define KRB5_CONF_IPROP_MASTER_ULOGSIZE "iprop_master_ulogsize" +#define KRB5_CONF_IPROP_PORT "iprop_port" +#define KRB5_CONF_IPROP_SLAVE_POLL "iprop_slave_poll" +#define KRB5_CONF_IPROP_LOGFILE "iprop_logfile" +#define KRB5_CONF_KADMIND_PORT "kadmind_port" +#define KRB5_CONF_KRB524_SERVER "krb524_server" +#define KRB5_CONF_KDC "kdc" +#define KRB5_CONF_KDCDEFAULTS "kdcdefaults" +#define KRB5_CONF_KDC_PORTS "kdc_ports" +#define KRB5_CONF_KDC_TCP_PORTS "kdc_tcp_ports" +#define KRB5_CONF_MAX_DGRAM_REPLY_SIZE "kdc_max_dgram_reply_size" +#define KRB5_CONF_KDC_DEFAULT_OPTIONS "kdc_default_options" +#define KRB5_CONF_KDC_TIMESYNC "kdc_timesync" +#define KRB5_CONF_KDC_REQ_CHECKSUM_TYPE "kdc_req_checksum_type" +#define KRB5_CONF_KEY_STASH_FILE "key_stash_file" +#define KRB5_CONF_KPASSWD_PORT "kpasswd_port" +#define KRB5_CONF_KPASSWD_SERVER "kpasswd_server" +#define KRB5_CONF_LIBDEFAULTS "libdefaults" +#define KRB5_CONF_LDAP_KDC_DN "ldap_kdc_dn" +#define KRB5_CONF_LDAP_KADMIN_DN "ldap_kadmind_dn" +#define KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE "ldap_service_password_file" +#define KRB5_CONF_LDAP_ROOT_CERTIFICATE_FILE "ldap_root_certificate_file" +#define KRB5_CONF_LDAP_SERVERS "ldap_servers" +#define KRB5_CONF_LDAP_CONNS_PER_SERVER "ldap_conns_per_server" +#define KRB5_CONF_NO_HOST_REFERRAL "no_host_referral" +#define KRB5_CONF_MASTER_KEY_NAME "master_key_name" +#define KRB5_CONF_MASTER_KEY_TYPE "master_key_type" +#define KRB5_CONF_MASTER_KDC "master_kdc" +#define KRB5_CONF_MAX_LIFE "max_life" +#define KRB5_CONF_MAX_RENEWABLE_LIFE "max_renewable_life" +#define KRB5_CONF_NOADDRESSES "noaddresses" +#define KRB5_CONF_PERMITTED_ENCTYPES "permitted_enctypes" +#define KRB5_CONF_PREFERRED_PREAUTH_TYPES "preferred_preauth_types" +#define KRB5_CONF_PROXIABLE "proxiable" +#define KRB5_CONF_RDNS "rdns" +#define KRB5_CONF_REALMS "realms" +#define KRB5_CONF_REALM_TRY_DOMAINS "realm_try_domains" +#define KRB5_CONF_REJECT_BAD_TRANSIT "reject_bad_transit" +#define KRB5_CONF_RENEW_LIFETIME "renew_lifetime" +#define KRB5_CONF_SAFE_CHECKSUM_TYPE "safe_checksum_type" +#define KRB5_CONF_SUPPORTED_ENCTYPES "supported_enctypes" +#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime" +#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit" +#define KRB5_CONF_VERIFY_AP_REQ_NOFAIL "verify_ap_req_nofail" +#define KRB5_CONF_V4_INSTANCE_CONVERT "v4_instance_convert" +#define KRB5_CONF_V4_REALM "v4_realm" +#define KRB5_CONF_ASTERISK "*" + +/* 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_MUST_USE_USER2USER 27 /* Server principal valid for */ + /* user2user only */ +#define KDC_ERR_PATH_NOT_ACCEPTED 28 /* KDC policy rejected transited */ + /* path */ +#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_KDC_NOT_TRUSTED 63 +#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_CERTIFICATE_MISMATCH 66 +#define KRB_AP_ERR_NO_TGT 67 +#define KDC_ERR_WRONG_REALM 68 +#define KRB_AP_ERR_USER_TO_USER_REQUIRED 69 +#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_REVOCATION_STATUS_UNAVAILABLE 74 +#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 + +/* + * 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; + +/* RFC 4537 */ +typedef struct _krb5_etype_list { + int length; + krb5_enctype *etypes; +} krb5_etype_list; + +/* + * 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" + +#include +#include + +#ifndef HAVE_STRDUP +extern char *strdup (const char *); +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include /* struct stat, stat() */ +#endif + +#ifdef HAVE_SYS_PARAM_H +#include /* MAXPATHLEN */ +#endif + +#ifdef HAVE_SYS_FILE_H +#include /* prototypes for file-related + syscalls; flags for open & + friends */ +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include + +#include "k5-gmt_mktime.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 ***); + +krb5_error_code krb5int_get_domain_realm_mapping + (krb5_context , const char *, char ***); + +/* 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_error_code +krb5int_locate_server (krb5_context, const krb5_data *realm, + struct addrlist *, enum locate_service_type svc, + int sockettype, int family); + +/* 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); + + /* In-place encryption/decryption of multiple buffers */ + krb5_error_code (*encrypt_iov) (const krb5_keyblock *key, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data); + + + krb5_error_code (*decrypt_iov) (const krb5_keyblock *key, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data); + +}; + +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); + + krb5_error_code (*hash_iov) (const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); + + krb5_error_code (*verify_iov) (const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + const krb5_crypto_iov *data, + size_t num_data, + const krb5_data *hash, + krb5_boolean *valid); +}; + +struct krb5_aead_provider { + krb5_error_code (*crypto_length) (const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length); + krb5_error_code (*encrypt_iov) (const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); + krb5_error_code (*decrypt_iov) (const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); +}; + +/* + * 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_hmac_iov +(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_crypto_iov *data, size_t num_data, + 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(__GNUC__) +static inline void krb5int_zap_data(void *ptr, size_t len) +{ + memset(ptr, 0, len); + asm volatile ("" : : "g" (ptr), "g" (len)); +} +#else +# define krb5int_zap_data(ptr, len) memset((volatile void *)ptr, 0, len) +#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 *); + +#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" + */ + +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 + +/* + * 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 + +#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. */ + struct krb5int_fast_request_state; +typedef struct _krb5_preauth_client_rock { + krb5_magic magic; + krb5_enctype *etype; + struct krb5int_fast_request_state *fast_state; +} 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 struct _krb5_pa_for_user { + krb5_principal user; + krb5_checksum cksum; + krb5_data auth_package; +} krb5_pa_for_user; + +enum { + KRB5_FAST_ARMOR_AP_REQUEST = 0x1 +}; + +typedef struct _krb5_fast_armor { + krb5_int32 armor_type; + krb5_data armor_value; +} krb5_fast_armor; +typedef struct _krb5_fast_armored_req { + krb5_magic magic; + krb5_fast_armor *armor; + krb5_checksum req_checksum; + krb5_enc_data enc_part; +} krb5_fast_armored_req; + +typedef struct _krb5_fast_req { + krb5_magic magic; + krb5_flags fast_options; + /* padata from req_body is used*/ + krb5_kdc_req *req_body; +} krb5_fast_req; + +/* Bits 0-15 are critical in fast options.*/ +#define UNSUPPORTED_CRITICAL_FAST_OPTIONS 0x00ff +#define KRB5_FAST_OPTION_HIDE_CLIENT_NAMES 0x01 + +typedef struct _krb5_fast_finished { + krb5_timestamp timestamp; + krb5_int32 usec; + krb5_principal client; + krb5_checksum ticket_checksum; +} krb5_fast_finished; + +typedef struct _krb5_fast_response { + krb5_magic magic; + krb5_pa_data **padata; + krb5_keyblock *strengthen_key; + krb5_fast_finished *finished; + krb5_int32 nonce; +} krb5_fast_response; + + +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 *); + +krb5_pa_data * krb5int_find_pa_data +(krb5_context, krb5_pa_data * const *, krb5_preauthtype); +/* Does not return a copy; original padata sequence responsible for freeing*/ + +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; + char * fast_ccache_name; +} krb5_gic_opt_private; + +/* + * On the Mac, ensure that the layout of krb5_gic_opt_ext matches that + * of krb5_get_init_creds_opt. + */ +#if TARGET_OS_MAC +# pragma pack(push,2) +#endif + +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; + +#if TARGET_OS_MAC +# pragma pack(pop) +#endif + +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 *); + +krb5_error_code +krb5int_copy_data_contents_add0 (krb5_context, const krb5_data *, krb5_data *); + +krb5_error_code +krb5int_copy_creds_contents (krb5_context, const krb5_creds *, krb5_creds *); + +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 *); +void KRB5_CALLCONV krb5_free_pa_for_user + (krb5_context, krb5_pa_for_user * ); +void KRB5_CALLCONV krb5_free_pa_svr_referral_data + (krb5_context, krb5_pa_svr_referral_data * ); +void KRB5_CALLCONV krb5_free_pa_server_referral_data + (krb5_context, krb5_pa_server_referral_data * ); +void KRB5_CALLCONV krb5_free_pa_pac_req + (krb5_context, krb5_pa_pac_req * ); +void KRB5_CALLCONV krb5_free_etype_list + (krb5_context, krb5_etype_list * ); + +void KRB5_CALLCONV krb5_free_fast_armor +(krb5_context, krb5_fast_armor *); +void KRB5_CALLCONV krb5_free_fast_armored_req +(krb5_context, krb5_fast_armored_req *); +void KRB5_CALLCONV krb5_free_fast_req(krb5_context, krb5_fast_req *); +void KRB5_CALLCONV krb5_free_fast_finished +(krb5_context, krb5_fast_finished *); +void KRB5_CALLCONV krb5_free_fast_response +(krb5_context, krb5_fast_response *); + +/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */ +#include "com_err.h" +#include "k5-plugin.h" + +struct _kdb5_dal_handle; /* private, in kdb5.h */ +typedef struct _kdb5_dal_handle kdb5_dal_handle; +struct _kdb_log_context; +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; + struct _krb5_os_context os_context; + char *default_realm; + profile_t profile; + kdb5_dal_handle *dal_handle; + 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; + 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; + + /* For Sun iprop code; does this really have to be here? */ + struct _kdb_log_context *kdblog_context; + + krb5_boolean allow_weak_crypto; +}; + +/* 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); + +struct krb5_safe_with_body { + krb5_safe *safe; + krb5_data *body; +}; +krb5_error_code encode_krb5_safe_with_body + (const struct krb5_safe_with_body *rep, 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 + (krb5_authdata *const *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 + (krb5_pa_data *const *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 + (krb5_etype_info_entry *const *, krb5_data **code); +krb5_error_code encode_krb5_etype_info2 + (krb5_etype_info_entry *const *, 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 **); + +#if 0 /* currently not compiled because we never use them */ +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 **); +#endif + +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 **); + +struct krb5_setpw_req { + krb5_principal target; + krb5_data password; +}; +krb5_error_code encode_krb5_setpw_req + (const struct krb5_setpw_req *rep, krb5_data **code); + +krb5_error_code encode_krb5_pa_for_user + (const krb5_pa_for_user * , krb5_data **); + +krb5_error_code encode_krb5_pa_svr_referral_data + (const krb5_pa_svr_referral_data * , krb5_data **); + +krb5_error_code encode_krb5_pa_server_referral_data + (const krb5_pa_server_referral_data * , krb5_data **); + +krb5_error_code encode_krb5_pa_pac_req + (const krb5_pa_pac_req * , krb5_data **); + +krb5_error_code encode_krb5_etype_list + (const krb5_etype_list * , krb5_data **); + +krb5_error_code encode_krb5_pa_fx_fast_request +(const krb5_fast_armored_req *, krb5_data **); +krb5_error_code encode_krb5_fast_req +(const krb5_fast_req *, krb5_data **); +krb5_error_code encode_krb5_pa_fx_fast_reply +(const krb5_enc_data *, krb5_data **); + +krb5_error_code encode_krb5_fast_response +(const krb5_fast_response *, krb5_data **); + +/************************************************************************* + * 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 **); + +krb5_error_code decode_krb5_setpw_req + (const krb5_data *, krb5_data **, krb5_principal *); + +krb5_error_code decode_krb5_pa_for_user + (const krb5_data *, krb5_pa_for_user **); + +krb5_error_code decode_krb5_pa_svr_referral_data + (const krb5_data *, krb5_pa_svr_referral_data **); + +krb5_error_code decode_krb5_pa_server_referral_data + (const krb5_data *, krb5_pa_server_referral_data **); + +krb5_error_code decode_krb5_pa_pac_req + (const krb5_data *, krb5_pa_pac_req **); + +krb5_error_code decode_krb5_etype_list + (const krb5_data *, krb5_etype_list **); + +krb5_error_code decode_krb5_pa_fx_fast_request +(const krb5_data *, krb5_fast_armored_req **); + +krb5_error_code decode_krb5_fast_req +(const krb5_data *, krb5_fast_req **); + + +krb5_error_code decode_krb5_pa_fx_fast_reply +(const krb5_data *, krb5_enc_data **); + +krb5_error_code decode_krb5_fast_response +(const krb5_data *, krb5_fast_response **); + +struct _krb5_key_data; /* kdb.h */ + +struct ldap_seqof_key_data { + krb5_int32 mkvno; /* Master key version number */ + struct _krb5_key_data *key_data; + krb5_int16 n_key_data; +}; +typedef struct ldap_seqof_key_data ldap_seqof_key_data; + +krb5_error_code +krb5int_ldap_encode_sequence_of_keys (const ldap_seqof_key_data *val, + krb5_data **code); + +krb5_error_code +krb5int_ldap_decode_sequence_of_keys (krb5_data *in, + ldap_seqof_key_data **rep); + +/************************************************************************* + * 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, + 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! */, + krb5_enctype); + +/* 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 + +/* value to use when requesting a keytab entry and KVNO doesn't matter */ +#define IGNORE_VNO 0 +/* value to use when requesting a keytab entry and enctype doesn't matter */ +#define IGNORE_ENCTYPE 0 + +/* + * 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 14 + +#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); + krb5_error_code (* krb5_auth_con_get_subkey_enctype)(krb5_context, krb5_auth_context, krb5_enctype *); + /* 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); + krb5_error_code (*clean_hostname)(krb5_context, const char *, char *, size_t); + + /* 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) (const ldap_seqof_key_data *val, + krb5_data **code); + + krb5_error_code + (*asn1_ldap_decode_sequence_of_keys) (krb5_data *in, + ldap_seqof_key_data **); + /* Used for encrypted challenge fast factor*/ + krb5_error_code (*encode_enc_data)(const krb5_enc_data *, krb5_data **); + krb5_error_code (*decode_enc_data)(const krb5_data *, krb5_enc_data **); + void (*free_enc_data)(krb5_context, krb5_enc_data *); + krb5_error_code (*encode_enc_ts)(const krb5_pa_enc_ts *, krb5_data **); + krb5_error_code (*decode_enc_ts)(const krb5_data *, krb5_pa_enc_ts **); + void (*free_enc_ts)(krb5_context, krb5_pa_enc_ts *); + krb5_error_code (*encrypt_helper) + (krb5_context, const krb5_keyblock *, krb5_keyusage, const krb5_data *, + krb5_enc_data *); + + /* + * 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); + + /* Exported for testing only! */ + krb5_error_code (*encode_krb5_sam_response_2) + (const krb5_sam_response_2 *rep, krb5_data **code); + krb5_error_code (*encode_krb5_enc_sam_response_enc_2) + (const krb5_enc_sam_response_enc_2 *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 + +/* 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_s { + const struct _krb5_cc_ops *ops; + krb5_pointer data; +}; +typedef struct krb5_cc_ptcursor_s *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_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 *); + krb5_error_code (KRB5_CALLCONV *lock)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *unlock)(krb5_context, krb5_ccache); +}; + +extern const krb5_cc_ops *krb5_cc_dfl_ops; + +krb5_error_code +krb5int_cc_os_default_name(krb5_context context, char **name); + +typedef struct _krb5_donot_replay { + krb5_magic magic; + krb5_ui_4 hash; + char *server; /* null-terminated */ + char *client; /* null-terminated */ + char *msghash; /* 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_rc_hash_message + (krb5_context context, + const krb5_data *message, char **out); + + +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); + +/* + * Referral definitions, debugging hooks, and subfunctions. + */ +#define KRB5_REFERRAL_MAXHOPS 10 +/* #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); + +/* 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); + +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); + +krb5_error_code +krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); +krb5_error_code +krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_data *input, krb5_data *output); + +struct _krb5_kt { /* should move into k5-int.h */ + krb5_magic magic; + const struct _krb5_kt_ops *ops; + krb5_pointer data; +}; + +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 *); + +krb5_error_code KRB5_CALLCONV krb5_get_tgs_ktypes + (krb5_context, + krb5_const_principal, + krb5_enctype **); + +void KRB5_CALLCONV krb5_free_ktypes + (krb5_context, krb5_enctype *); + +krb5_boolean krb5_is_permitted_enctype + (krb5_context, krb5_enctype); + +typedef struct +{ + krb5_enctype *etype; + krb5_boolean *etype_ok; + krb5_int32 etype_count; +} krb5_etypes_permitted; + +krb5_boolean krb5_is_permitted_enctype_ext + ( krb5_context, krb5_etypes_permitted *); + +krb5_boolean KRB5_CALLCONV krb5_c_weak_enctype(krb5_enctype); + +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_get_cred_via_tkt + (krb5_context, + krb5_creds *, + krb5_flags, + krb5_address * const *, + krb5_creds *, + krb5_creds **); + +krb5_error_code KRB5_CALLCONV krb5_copy_addr + (krb5_context, + const krb5_address *, + krb5_address **); + +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_subkey_extended + (krb5_context, + const krb5_keyblock *, + krb5_enctype, + krb5_keyblock **); +krb5_error_code krb5_generate_seq_number + (krb5_context, + const krb5_keyblock *, krb5_ui_4 *); + +krb5_error_code KRB5_CALLCONV krb5_kt_register + (krb5_context, + const struct _krb5_kt_ops * ); + +/* use krb5_free_keytab_entry_contents instead */ +krb5_error_code KRB5_CALLCONV krb5_kt_free_entry + (krb5_context, + krb5_keytab_entry * ); + +krb5_error_code krb5_principal2salt_norealm + (krb5_context, + krb5_const_principal, krb5_data *); + +unsigned int KRB5_CALLCONV krb5_get_notification_message + (void); + +/* chk_trans.c */ +krb5_error_code krb5_check_transited_list + (krb5_context, const krb5_data *trans, + const krb5_data *realm1, const krb5_data *realm2); + +/* free_rtree.c */ +void krb5_free_realm_tree + (krb5_context, + krb5_principal *); + +void KRB5_CALLCONV krb5_free_authenticator_contents + (krb5_context, krb5_authenticator * ); + +void KRB5_CALLCONV krb5_free_address + (krb5_context, krb5_address * ); + +void KRB5_CALLCONV krb5_free_enc_tkt_part + (krb5_context, krb5_enc_tkt_part * ); + +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 * ); +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 *); +void KRB5_CALLCONV krb5_free_cred_enc_part + (krb5_context, krb5_cred_enc_part *); +void KRB5_CALLCONV krb5_free_pa_data + (krb5_context, krb5_pa_data **); +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 **); +void KRB5_CALLCONV krb5_free_passwd_phrase_element + (krb5_context, passwd_phrase_element *); +void KRB5_CALLCONV krb5_free_alt_method + (krb5_context, krb5_alt_method *); +void KRB5_CALLCONV krb5_free_enc_data + (krb5_context, krb5_enc_data *); +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); +krb5_error_code krb5int_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 * , krb5_keyblock **subkey); + /* The subkey field is an output parameter; if a + * tgs-rep is received then the subkey will be filled + * in with the subkey needed to decrypt the TGS + * response. Otherwise it will be set to null. + */ +krb5_error_code krb5int_decode_tgs_rep + (krb5_context, + krb5_data *, + const krb5_keyblock *, krb5_keyusage, + krb5_kdc_rep ** ); +krb5_error_code krb5int_find_authdata +(krb5_context context, krb5_authdata *const * ticket_authdata, + krb5_authdata * const *ap_req_authdata, + krb5_authdatatype ad_type, + krb5_authdata ***results); + +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 **); +krb5_error_code KRB5_CALLCONV krb5_cc_register + (krb5_context, + const krb5_cc_ops *, + krb5_boolean ); +krb5_error_code krb5_walk_realm_tree + (krb5_context, + const krb5_data *, + const krb5_data *, + krb5_principal **, + int); +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); +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 *); + +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 **); + +krb5_error_code krb5_auth_con_get_subkey_enctype + (krb5_context context, + krb5_auth_context, + krb5_enctype *); + +krb5_error_code KRB5_CALLCONV +krb5int_server_decrypt_ticket_keyblock + (krb5_context context, + const krb5_keyblock *key, + krb5_ticket *ticket); + +krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *); +krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *); +krb5_error_code krb5int_write_messages (krb5_context, krb5_pointer, krb5_data *, int); +int krb5_net_read (krb5_context, int , char *, int); +int krb5_net_write (krb5_context, int , const char *, int); + +krb5_error_code KRB5_CALLCONV krb5_get_realm_domain + (krb5_context, + const char *, + char ** ); + +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 *); + +krb5_error_code krb5_set_debugging_time + (krb5_context, krb5_timestamp, krb5_int32); +krb5_error_code krb5_use_natural_time + (krb5_context); +krb5_error_code krb5_set_time_offsets + (krb5_context, krb5_timestamp, krb5_int32); +krb5_error_code krb5int_check_clockskew(krb5_context, krb5_timestamp); +/* + * 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); + +/* Internal principal function used by KIM to avoid code duplication */ +krb5_error_code KRB5_CALLCONV +krb5int_build_principal_alloc_va(krb5_context context, + krb5_principal *princ, + unsigned int rlen, + const char *realm, + const char *first, + va_list ap); + +/* Some data comparison and conversion functions. */ +#if 0 +static inline int data_cmp(krb5_data d1, krb5_data d2) +{ + if (d1.length < d2.length) return -1; + if (d1.length > d2.length) return 1; + return memcmp(d1.data, d2.data, d1.length); +} +static inline int data_eq (krb5_data d1, krb5_data d2) +{ + return data_cmp(d1, d2) == 0; +} +#else +static inline int data_eq (krb5_data d1, krb5_data d2) +{ + return (d1.length == d2.length + && !memcmp(d1.data, d2.data, d1.length)); +} +#endif +static inline krb5_data string2data (char *str) +{ + krb5_data d; + d.magic = KV5M_DATA; + d.length = strlen(str); + d.data = str; + return d; +} +static inline int data_eq_string (krb5_data d, char *s) +{ + return data_eq(d, string2data(s)); +} +static inline int authdata_eq (krb5_authdata a1, krb5_authdata a2) +{ + return (a1.ad_type == a2.ad_type + && a1.length == a2.length + && !memcmp(a1.contents, a2.contents, a1.length)); +} + +krb5_error_code KRB5_CALLCONV +krb5int_pac_sign(krb5_context context, + krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, + krb5_data *data); + +#ifdef DEBUG_ERROR_LOCATIONS +#define krb5_set_error_message(ctx, code, ...) \ + krb5_set_error_message_fl(ctx, code, __FILE__, __LINE__, __VA_ARGS__) +#endif + +#endif /* _KRB5_INT_H */ diff --git a/krb5-1-7/src/include/k5-ipc_stream.h b/krb5-1-7/src/include/k5-ipc_stream.h new file mode 100644 index 000000000..71bbaa1e7 --- /dev/null +++ b/krb5-1-7/src/include/k5-ipc_stream.h @@ -0,0 +1,77 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef K5_IPC_STREAM_H +#define K5_IPC_STREAM_H + +#include "k5-platform.h" + +struct k5_ipc_stream_s; +typedef struct k5_ipc_stream_s *k5_ipc_stream; + + +int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream); + +uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream); + +uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream); + +const char *k5_ipc_stream_data (k5_ipc_stream in_stream); + +uint32_t k5_ipc_stream_read (k5_ipc_stream in_stream, + void *io_data, + uint64_t in_size); +uint32_t k5_ipc_stream_write (k5_ipc_stream in_stream, + const void *in_data, + uint64_t in_size); + +uint32_t k5_ipc_stream_read_string (k5_ipc_stream io_stream, + char **out_string); +uint32_t k5_ipc_stream_write_string (k5_ipc_stream io_stream, + const char *in_string); +void k5_ipc_stream_free_string (char *in_string); + +uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream io_stream, + int32_t *out_int32); +uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream, + int32_t in_int32); + +uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream io_stream, + uint32_t *out_uint32); +uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream, + uint32_t in_uint32); + +uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream io_stream, + int64_t *out_int64); +uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream, + int64_t in_int64); + +uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream io_stream, + uint64_t *out_uint64); +uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream, + uint64_t in_uint64); + +#endif /* K5_IPC_STREAM_H */ diff --git a/krb5-1-7/src/include/k5-platform.h b/krb5-1-7/src/include/k5-platform.h new file mode 100644 index 000000000..5c7789725 --- /dev/null +++ b/krb5-1-7/src/include/k5-platform.h @@ -0,0 +1,976 @@ +/* + * k5-platform.h + * + * Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + * + [u]int{8,16,32}_t types + * + 64-bit types and load/store code + * + SIZE_MAX + * + shared library init/fini hooks + * + consistent getpwnam/getpwuid interfaces + * + va_copy fudged if not provided + * + [v]asprintf + */ + +#ifndef K5_PLATFORM_H +#define K5_PLATFORM_H + +#include "autoconf.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define CAN_COPY_VA_LIST +#endif + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +/* 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 +# 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 +# endif +# ifdef HAVE_INTTYPES_H +# include +# 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 + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t)((size_t)0 - 1)) +#endif + +#ifndef UINT64_MAX +# define UINT64_MAX ((UINT64_TYPE)((UINT64_TYPE)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 +#elif HAVE_MACHINE_ENDIAN_H +# include +#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 +# define SWAP16 bswap_16 +# define SWAP32 bswap_32 +# ifdef HAVE_BSWAP_64 +# define SWAP64 bswap_64 +# endif +#endif +#if TARGET_OS_MAC +# include +# if 0 /* This causes compiler warnings. */ +# define SWAP16 OSSwapInt16 +# else +# define SWAP16 k5_swap16 +static inline unsigned int k5_swap16 (unsigned int x) { + x &= 0xffff; + return (x >> 8) | ((x & 0xff) << 8); +} +# endif +# define SWAP32 OSSwapInt32 +# define SWAP64 OSSwapInt64 +#endif + +/* Note that on Windows at least this file can be included from C++ + source, so casts *from* void* are required. */ +static inline void +store_16_be (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(16,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus) + PUTSWAPPED(16,p,val); +#else + p[0] = (val >> 8) & 0xff; + p[1] = (val ) & 0xff; +#endif +} +static inline void +store_32_be (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(32,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus) + 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, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(64,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus) + 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 void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(16,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus) + return GETSWAPPED(16,p); +#else + return (p[1] | (p[0] << 8)); +#endif +} +static inline unsigned int +load_32_be (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(32,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus) + 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 void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(64,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus) + 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, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(16,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus) + PUTSWAPPED(16,p,val); +#else + p[1] = (val >> 8) & 0xff; + p[0] = (val ) & 0xff; +#endif +} +static inline void +store_32_le (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(32,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus) + 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, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(64,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus) + 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 void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(16,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus) + return GETSWAPPED(16,p); +#else + return (p[0] | (p[1] << 8)); +#endif +} +static inline unsigned int +load_32_le (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(32,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus) + 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 void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(64,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus) + return GETSWAPPED(64,p); +#else + return ((UINT64_TYPE)load_32_le(p+4) << 32) | load_32_le(p); +#endif +} + +static inline unsigned short +load_16_n (const void *p) +{ +#ifdef _WIN32 + unsigned __int16 n; +#else + uint16_t n; +#endif + memcpy(&n, p, 2); + return n; +} +static inline unsigned int +load_32_n (const void *p) +{ +#ifdef _WIN32 + unsigned __int32 n; +#else + uint32_t n; +#endif + memcpy(&n, p, 4); + return n; +} +static inline UINT64_TYPE +load_64_n (const void *p) +{ + UINT64_TYPE n; + memcpy(&n, p, 8); + return n; +} + +/* Assume for simplicity that these swaps are identical. */ +static inline UINT64_TYPE +k5_htonll (UINT64_TYPE val) +{ +#ifdef K5_BE + return val; +#elif defined K5_LE && defined SWAP64 + return SWAP64 (val); +#else + return load_64_be ((unsigned char *)&val); +#endif +} +static inline UINT64_TYPE +k5_ntohll (UINT64_TYPE val) +{ + return k5_htonll (val); +} + +/* 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 + +/* Ensure, if possible, that the indicated file descriptor won't be + kept open if we exec another process (e.g., launching a ccapi + server). If we don't know how to do it... well, just go about our + business. Probably most callers won't check the return status + anyways. */ + +#if 0 +static inline int +set_cloexec_fd(int fd) +{ +#if defined(F_SETFD) +# ifdef FD_CLOEXEC + if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) + return errno; +# else + if (fcntl(fd, F_SETFD, 1) != 0) + return errno; +# endif +#endif + return 0; +} + +static inline int +set_cloexec_file(FILE *f) +{ + return set_cloexec_fd(fileno(f)); +} +#else +/* Macros make the Sun compiler happier, and all variants of this do a + single evaluation of the argument, and fcntl and fileno should + produce reasonable error messages on type mismatches, on any system + with F_SETFD. */ +#ifdef F_SETFD +# ifdef FD_CLOEXEC +# define set_cloexec_fd(FD) (fcntl((FD), F_SETFD, FD_CLOEXEC) ? errno : 0) +# else +# define set_cloexec_fd(FD) (fcntl((FD), F_SETFD, 1) ? errno : 0) +# endif +#else +# define set_cloexec_fd(FD) ((FD),0) +#endif +#define set_cloexec_file(F) set_cloexec_fd(fileno(F)) +#endif + + + +/* Since the original ANSI C spec left it undefined whether or + how you could copy around a va_list, C 99 added va_copy. + For old implementations, let's do our best to fake it. + + XXX Doesn't yet handle implementations with __va_copy (early draft) + or GCC's __builtin_va_copy. */ +#if defined(HAS_VA_COPY) || defined(va_copy) +/* Do nothing. */ +#elif defined(CAN_COPY_VA_LIST) +#define va_copy(dest, src) ((dest) = (src)) +#else +/* Assume array type, but still simply copyable. + + There is, theoretically, the possibility that va_start will + allocate some storage pointed to by the va_list, and in that case + we'll just lose. If anyone cares, we could try to devise a test + for that case. */ +#define va_copy(dest, src) memcmp(dest, src, sizeof(va_list)) +#endif + +/* Provide strlcpy/strlcat interfaces. */ +#ifndef HAVE_STRLCPY +#define strlcpy krb5int_strlcpy +#define strlcat krb5int_strlcat +extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz); +extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz); +#endif + +/* Provide [v]asprintf interfaces. */ +#ifndef HAVE_VSNPRINTF +#ifdef _WIN32 +static inline int +vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + va_list args_copy; + int length; + + va_copy(args_copy, args); + length = _vscprintf(format, args_copy); + va_end(args_copy); + if (size) + _vsnprintf(str, size, format, args); + return length; +} +static inline int +snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + n = vsnprintf(str, size, format, args); + va_end(args); + return n; +} +#else /* not win32 */ +#error We need an implementation of vsnprintf. +#endif /* win32? */ +#endif /* no vsnprintf */ + +#ifndef HAVE_VASPRINTF + +extern int krb5int_vasprintf(char **, const char *, va_list) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; +extern int krb5int_asprintf(char **, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +#define vasprintf krb5int_vasprintf +/* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF. */ +#define asprintf krb5int_asprintf + +#elif defined(NEED_VASPRINTF_PROTO) + +extern int vasprintf(char **, const char *, va_list) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; +extern int asprintf(char **, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +#endif /* have vasprintf and prototype? */ + +/* Return true if the snprintf return value RESULT reflects a buffer + overflow for the buffer size SIZE. + + We cast the result to unsigned int for two reasons. First, old + implementations of snprintf (such as the one in Solaris 9 and + prior) return -1 on a buffer overflow. Casting the result to -1 + will convert that value to UINT_MAX, which should compare larger + than any reasonable buffer size. Second, comparing signed and + unsigned integers will generate warnings with some compilers, and + can have unpredictable results, particularly when the relative + widths of the types is not known (size_t may be the same width as + int or larger). +*/ +#define SNPRINTF_OVERFLOW(result, size) \ + ((unsigned int)(result) >= (size_t)(size)) + +#ifndef HAVE_MKSTEMP +extern int krb5int_mkstemp(char *); +#define mkstemp krb5int_mkstemp +#endif + +/* Fudge for future adoption of gettext or the like. */ +#ifndef _ +#define _(X) (X) +#endif + +#endif /* K5_PLATFORM_H */ diff --git a/krb5-1-7/src/include/k5-plugin.h b/krb5-1-7/src/include/k5-plugin.h new file mode 100644 index 000000000..f5f4f43c2 --- /dev/null +++ b/krb5-1-7/src/include/k5-plugin.h @@ -0,0 +1,109 @@ +/* + * 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. */ + +#ifndef K5_PLUGIN_H +#define K5_PLUGIN_H + +#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 +#elif defined(HAVE_INTTYPES_H) +# include +#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)); + +#endif /* K5_PLUGIN_H */ diff --git a/krb5-1-7/src/include/k5-thread.h b/krb5-1-7/src/include/k5-thread.h new file mode 100644 index 000000000..821fe8457 --- /dev/null +++ b/krb5-1-7/src/include/k5-thread.h @@ -0,0 +1,454 @@ +/* + * include/k5-thread.h + * + * Copyright 2004,2005,2006,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + 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), + 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. + + + 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. */ + +#include + + +/* The mutex structure we use, k5_mutex_t, is defined to some + OS-specific bits. The use of multiple layers of typedefs are an + artifact resulting from debugging code we once used, implemented as + wrappers around the OS mutex scheme. + + The OS specific bits, in k5_os_mutex, break down into three primary + implementations, POSIX threads, Windows threads, and no thread + support. However, the POSIX thread version is further subdivided: + In one case, we can determine at run time whether the thread + library is linked into the application, and use it only if it is + present; in the other case, we cannot, and the thread library must + be linked in always, but can be used unconditionally. In the + former case, the k5_os_mutex structure needs to hold both the POSIX + and the non-threaded versions. + + The various k5_os_mutex_* operations are the OS-specific versions, + applied to the OS-specific data, and k5_mutex_* uses k5_os_mutex_* + to do the OS-specific parts of the work. */ + +/* Define the OS mutex bit. */ + +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; +} + +/* 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_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 + +/* Weak reference support, etc. + + Linux: Stub mutex routines exist, but pthread_once does not. + + Solaris <10: 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. + + Solaris 10: The real thread support now lives in libc, and + libpthread is just a filter object. So we might as well use the + real functions unconditionally. Since we haven't got a test for + this property yet, we use NO_WEAK_PTHREADS defined in aclocal.m4 + depending on the OS type. + + 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. */ +extern int krb5int_pthread_loaded(void) +#ifdef __GNUC__ + /* We should always get the same answer for the life of the process. */ + __attribute__((const)) +#endif + ; +#if defined(HAVE_PRAGMA_WEAK_REF) && !defined(NO_WEAK_PTHREADS) +# 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 +# define K5_PTHREADS_LOADED (krb5int_pthread_loaded()) +# define USE_PTHREAD_LOCK_ONLY_IF_LOADED + +/* 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 + +/* no pragma weak support */ +# define K5_PTHREADS_LOADED (1) + +typedef pthread_once_t k5_once_t; +# define K5_ONCE_INIT PTHREAD_ONCE_INIT +# define k5_once pthread_once + +#endif + +#if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__)) +# 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 + +typedef pthread_mutex_t k5_os_mutex; +# define K5_OS_MUTEX_PARTIAL_INITIALIZER \ + PTHREAD_MUTEX_INITIALIZER + +#ifdef USE_PTHREAD_LOCK_ONLY_IF_LOADED + +# define k5_os_mutex_finish_init(M) (0) +# define k5_os_mutex_init(M) \ + (K5_PTHREADS_LOADED ? pthread_mutex_init((M), 0) : 0) +# define k5_os_mutex_destroy(M) \ + (K5_PTHREADS_LOADED ? pthread_mutex_destroy((M)) : 0) +# define k5_os_mutex_lock(M) \ + (K5_PTHREADS_LOADED ? pthread_mutex_lock(M) : 0) +# define k5_os_mutex_unlock(M) \ + (K5_PTHREADS_LOADED ? pthread_mutex_unlock(M) : 0) + +#else + +static inline int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; } +# define k5_os_mutex_init(M) pthread_mutex_init((M), 0) +# define k5_os_mutex_destroy(M) pthread_mutex_destroy((M)) +# define k5_os_mutex_lock(M) pthread_mutex_lock(M) +# define k5_os_mutex_unlock(M) pthread_mutex_unlock(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()) + +#else + +# error "Thread support enabled, but thread system unknown" + +#endif + + + + +typedef k5_os_mutex k5_mutex_t; +#define K5_MUTEX_PARTIAL_INITIALIZER K5_OS_MUTEX_PARTIAL_INITIALIZER +static inline int k5_mutex_init(k5_mutex_t *m) +{ + return k5_os_mutex_init(m); +} +static inline int k5_mutex_finish_init(k5_mutex_t *m) +{ + return k5_os_mutex_finish_init(m); +} +#define k5_mutex_destroy(M) \ + (k5_os_mutex_destroy(M)) + +#if __GNUC__ >= 4 +static int k5_mutex_lock(k5_mutex_t *) + __attribute__((warn_unused_result)); +#endif +static inline int k5_mutex_lock(k5_mutex_t *m) +{ + return k5_os_mutex_lock(m); +} + +#define k5_mutex_unlock(M) \ + (k5_os_mutex_unlock(M)) + +#define k5_mutex_assert_locked(M) ((void)(M)) +#define k5_mutex_assert_unlocked(M) ((void)(M)) +#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_GSS_KRB5_ERROR_MESSAGE, + K5_KEY_KIM_ERROR_MESSAGE, +#if defined(__MACH__) && defined(__APPLE__) + K5_KEY_IPC_CONNECTION_INFO, + K5_KEY_COM_ERR_REENTER, +#endif + 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 *) +#if __GNUC__ >= 4 + __attribute__((warn_unused_result)) +#endif + ; +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. */ +#if defined(PLUGIN) || (defined(CONFIG_SMALL) && !defined(THREAD_SUPPORT_IMPL)) +#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-7/src/include/k5-unicode.h b/krb5-1-7/src/include/k5-unicode.h new file mode 100644 index 000000000..0f8f12a38 --- /dev/null +++ b/krb5-1-7/src/include/k5-unicode.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008 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. + */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2008 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ + +#ifndef K5_UNICODE_H +#define K5_UNICODE_H + +#include "autoconf.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "k5-utf8.h" + +typedef krb5_ucs4 krb5_unicode; + +int krb5int_ucstrncmp( + const krb5_unicode *, + const krb5_unicode *, + size_t); + +int krb5int_ucstrncasecmp( + const krb5_unicode *, + const krb5_unicode *, + size_t); + +krb5_unicode *krb5int_ucstrnchr( + const krb5_unicode *, + size_t, + krb5_unicode); + +krb5_unicode *krb5int_ucstrncasechr( + const krb5_unicode *, + size_t, + krb5_unicode); + +void krb5int_ucstr2upper( + krb5_unicode *, + size_t); + +#define KRB5_UTF8_NOCASEFOLD 0x0U +#define KRB5_UTF8_CASEFOLD 0x1U +#define KRB5_UTF8_ARG1NFC 0x2U +#define KRB5_UTF8_ARG2NFC 0x4U +#define KRB5_UTF8_APPROX 0x8U + +krb5_error_code krb5int_utf8_normalize( + krb5_data *, + krb5_data **, + unsigned); + +int krb5int_utf8_normcmp( + const krb5_data *, + const krb5_data *, + unsigned); + +#endif /* K5_UNICODE_H */ diff --git a/krb5-1-7/src/include/k5-utf8.h b/krb5-1-7/src/include/k5-utf8.h new file mode 100644 index 000000000..e3f134b56 --- /dev/null +++ b/krb5-1-7/src/include/k5-utf8.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2008 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. + */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2008 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ + +#ifndef K5_UTF8_H +#define K5_UTF8_H + +#include "autoconf.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#if INT_MAX == 0x7fff +typedef unsigned int krb5_ucs2; +#elif SHRT_MAX == 0x7fff +typedef unsigned short krb5_ucs2; +#else +#error undefined 16 bit type +#endif + +#if INT_MAX == 0x7fffffffL +typedef int krb5_ucs4; +#elif LONG_MAX == 0x7fffffffL +typedef long krb5_ucs4; +#elif SHRT_MAX == 0x7fffffffL +typedef short krb5_ucs4; +#else +#error: undefined 32 bit type +#endif + +#define KRB5_MAX_UTF8_LEN (sizeof(krb5_ucs2) * 3/2) + +int krb5int_utf8_to_ucs2(const char *p, krb5_ucs2 *out); +size_t krb5int_ucs2_to_utf8(krb5_ucs2 c, char *buf); + +int krb5int_utf8_to_ucs4(const char *p, krb5_ucs4 *out); +size_t krb5int_ucs4_to_utf8(krb5_ucs4 c, char *buf); + +int +krb5int_ucs2s_to_utf8s(const krb5_ucs2 *ucs2s, + char **utf8s, + size_t *utf8slen); + +int +krb5int_ucs2cs_to_utf8s(const krb5_ucs2 *ucs2s, + size_t ucs2slen, + char **utf8s, + size_t *utf8slen); + +int +krb5int_ucs2les_to_utf8s(const unsigned char *ucs2les, + char **utf8s, + size_t *utf8slen); + +int +krb5int_ucs2lecs_to_utf8s(const unsigned char *ucs2les, + size_t ucs2leslen, + char **utf8s, + size_t *utf8slen); + +int +krb5int_utf8s_to_ucs2s(const char *utf8s, + krb5_ucs2 **ucs2s, + size_t *ucs2chars); + +int +krb5int_utf8cs_to_ucs2s(const char *utf8s, + size_t utf8slen, + krb5_ucs2 **ucs2s, + size_t *ucs2chars); + +int +krb5int_utf8s_to_ucs2les(const char *utf8s, + unsigned char **ucs2les, + size_t *ucs2leslen); + +int +krb5int_utf8cs_to_ucs2les(const char *utf8s, + size_t utf8slen, + unsigned char **ucs2les, + size_t *ucs2leslen); + +/* returns the number of bytes in the UTF-8 string */ +size_t krb5int_utf8_bytes(const char *); +/* returns the number of UTF-8 characters in the string */ +size_t krb5int_utf8_chars(const char *); +/* returns the number of UTF-8 characters in the counted string */ +size_t krb5int_utf8c_chars(const char *, size_t); +/* returns the length (in bytes) of the UTF-8 character */ +int krb5int_utf8_offset(const char *); +/* returns the length (in bytes) indicated by the UTF-8 character */ +int krb5int_utf8_charlen(const char *); + +/* returns the length (in bytes) indicated by the UTF-8 character + * also checks that shortest possible encoding was used + */ +int krb5int_utf8_charlen2(const char *); + +/* copies a UTF-8 character and returning number of bytes copied */ +int krb5int_utf8_copy(char *, const char *); + +/* returns pointer of next UTF-8 character in string */ +char *krb5int_utf8_next( const char *); +/* returns pointer of previous UTF-8 character in string */ +char *krb5int_utf8_prev( const char *); + +/* primitive ctype routines -- not aware of non-ascii characters */ +int krb5int_utf8_isascii( const char *); +int krb5int_utf8_isalpha( const char *); +int krb5int_utf8_isalnum( const char *); +int krb5int_utf8_isdigit( const char *); +int krb5int_utf8_isxdigit( const char *); +int krb5int_utf8_isspace( const char *); + +/* span characters not in set, return bytes spanned */ +size_t krb5int_utf8_strcspn( const char* str, const char *set); +/* span characters in set, return bytes spanned */ +size_t krb5int_utf8_strspn( const char* str, const char *set); +/* return first occurance of character in string */ +char *krb5int_utf8_strchr( const char* str, const char *chr); +/* return first character of set in string */ +char *krb5int_utf8_strpbrk( const char* str, const char *set); +/* reentrant tokenizer */ +char *krb5int_utf8_strtok( char* sp, const char* sep, char **last); + +/* Optimizations */ +extern const char krb5int_utf8_lentab[128]; +extern const char krb5int_utf8_mintab[32]; + +#define KRB5_UTF8_ISASCII(p) ( !(*(const unsigned char *)(p) & 0x80 ) ) +#define KRB5_UTF8_CHARLEN(p) ( KRB5_UTF8_ISASCII(p) \ + ? 1 : krb5int_utf8_lentab[*(const unsigned char *)(p) ^ 0x80] ) + +/* This is like CHARLEN but additionally validates to make sure + * the char used the shortest possible encoding. + * 'l' is used to temporarily hold the result of CHARLEN. + */ +#define KRB5_UTF8_CHARLEN2(p, l) ( ( ( l = KRB5_UTF8_CHARLEN( p )) < 3 || \ + ( krb5int_utf8_mintab[*(const unsigned char *)(p) & 0x1f] & (p)[1] ) ) ? \ + l : 0 ) + +#define KRB5_UTF8_OFFSET(p) ( KRB5_UTF8_ISASCII(p) \ + ? 1 : krb5int_utf8_offset((p)) ) + +#define KRB5_UTF8_COPY(d,s) ( KRB5_UTF8_ISASCII(s) \ + ? (*(d) = *(s), 1) : krb5int_utf8_copy((d),(s)) ) + +#define KRB5_UTF8_NEXT(p) ( KRB5_UTF8_ISASCII(p) \ + ? (char *)(p)+1 : krb5int_utf8_next((p)) ) + +#define KRB5_UTF8_INCR(p) ((p) = KRB5_UTF8_NEXT(p)) + +/* For symmetry */ +#define KRB5_UTF8_PREV(p) (krb5int_utf8_prev((p))) +#define KRB5_UTF8_DECR(p) ((p)=KRB5_UTF8_PREV((p))) + +/* + * these macros assume 'x' is an ASCII x + * and assume the "C" locale + */ +#define KRB5_ASCII(c) (!((c) & 0x80)) +#define KRB5_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define KRB5_DIGIT(c) ((c) >= '0' && (c) <= '9') +#define KRB5_LOWER(c) ((c) >= 'a' && (c) <= 'z') +#define KRB5_UPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define KRB5_ALPHA(c) (KRB5_LOWER(c) || KRB5_UPPER(c)) +#define KRB5_ALNUM(c) (KRB5_ALPHA(c) || KRB5_DIGIT(c)) + +#define KRB5_LDH(c) (KRB5_ALNUM(c) || (c) == '-') + +#define KRB5_HEXLOWER(c) ((c) >= 'a' && (c) <= 'f') +#define KRB5_HEXUPPER(c) ((c) >= 'A' && (c) <= 'F') +#define KRB5_HEX(c) (KRB5_DIGIT(c) || \ + KRB5_HEXLOWER(c) || KRB5_HEXUPPER(c)) + +#endif /* K5_UTF8_H */ diff --git a/krb5-1-7/src/include/k5-util.h b/krb5-1-7/src/include/k5-util.h new file mode 100644 index 000000000..7bb8cfbe9 --- /dev/null +++ b/krb5-1-7/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 +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +#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-7/src/include/kdb.h b/krb5-1-7/src/include/kdb.h new file mode 100644 index 000000000..ea81cfeef --- /dev/null +++ b/krb5-1-7/src/include/kdb.h @@ -0,0 +1,916 @@ +/* + * 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. + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* This API is not considered as stable as the main krb5 API. + * + * - We may make arbitrary incompatible changes between feature + * releases (e.g. from 1.7 to 1.8). + * - We will make some effort to avoid making incompatible changes for + * bugfix releases, but will make them if necessary. + */ + +#ifndef KRB5_KDB5__ +#define KRB5_KDB5__ + +#include + +/* 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 +#define KRB5_KDB_SALTTYPE_CERTHASH 6 + +/* 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 +#define KRB5_KDB_OK_AS_DELEGATE 0x00100000 + +/* Creation flags */ +#define KRB5_KDB_CREATE_BTREE 0x00000001 +#define KRB5_KDB_CREATE_HASH 0x00000002 + +#if !defined(_WIN32) + +/* + * 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 +#define KRB5_TL_MKVNO 0x0008 +#define KRB5_TL_ACTKVNO 0x0009 +#define KRB5_TL_MKEY_AUX 0x000a + +/* version number for KRB5_TL_ACTKVNO data */ +#define KRB5_TL_ACTKVNO_VER 1 + +/* version number for KRB5_TL_MKEY_AUX data */ +#define KRB5_TL_MKEY_AUX_VER 1 + +typedef struct _krb5_actkvno_node { + struct _krb5_actkvno_node *next; + krb5_kvno act_kvno; + krb5_timestamp act_time; +} krb5_actkvno_node; + +typedef struct _krb5_mkey_aux_node { + struct _krb5_mkey_aux_node *next; + krb5_kvno mkey_kvno; /* kvno of mkey protecting the latest_mkey */ + krb5_key_data latest_mkey; /* most recent mkey */ +} krb5_mkey_aux_node; + +typedef struct _krb5_keylist_node { + krb5_keyblock keyblock; + krb5_kvno kvno; + struct _krb5_keylist_node *next; +} krb5_keylist_node; + +/* + * 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. + */ +#ifdef _KRB5_INT_H +#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) +#endif /* _KRB5_INT_H */ + +#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_setup_lib_handle(krb5_context kcontext); +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_set_mkey_list( krb5_context context, + krb5_keylist_node * keylist); + +krb5_error_code krb5_db_get_mkey_list( krb5_context kcontext, + krb5_keylist_node ** keylist); + +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 *keyfile, + krb5_principal mname, + krb5_kvno kvno, + krb5_keyblock *key, + char *master_pwd); +krb5_error_code krb5_db_store_master_key_list ( krb5_context kcontext, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + 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_kvno *kvno, + krb5_data *salt, + krb5_keyblock *key); +krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext, + krb5_principal mprinc, + krb5_kvno kvno, + krb5_keyblock *mkey ); +krb5_error_code +krb5_db_fetch_mkey_list( krb5_context context, + krb5_principal mname, + const krb5_keyblock * mkey, + krb5_kvno mkvno, + krb5_keylist_node **mkeys_list ); + +krb5_error_code +krb5_db_free_mkey_list( krb5_context context, + krb5_keylist_node *mkey_list ); + +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_fetch_act_key_list(krb5_context context, + krb5_principal princ, + krb5_actkvno_node **act_key_list); + +krb5_error_code +krb5_dbe_find_act_mkey( krb5_context context, + krb5_keylist_node * mkey_list, + krb5_actkvno_node * act_mkey_list, + krb5_kvno * act_kvno, + krb5_keyblock ** act_mkey); + +krb5_error_code +krb5_dbe_find_mkey( krb5_context context, + krb5_keylist_node * mkey_list, + krb5_db_entry * entry, + krb5_keyblock ** mkey); + +krb5_error_code +krb5_dbe_lookup_mkvno( krb5_context context, + krb5_db_entry * entry, + krb5_kvno * mkvno); + +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_lookup_mkey_aux( krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node ** mkey_aux_data_list); +krb5_error_code +krb5_dbe_update_mkvno( krb5_context context, + krb5_db_entry * entry, + krb5_kvno mkvno); + +krb5_error_code +krb5_dbe_lookup_actkvno( krb5_context context, + krb5_db_entry * entry, + krb5_actkvno_node ** actkvno_list); + +krb5_error_code +krb5_dbe_update_mkey_aux( krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node * mkey_aux_data_list); + +krb5_error_code +krb5_dbe_update_actkvno(krb5_context context, + krb5_db_entry * entry, + const krb5_actkvno_node *actkvno_list); + +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_delete_tl_data( krb5_context context, + krb5_db_entry * entry, + krb5_int16 tl_data_type); + +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); + +int +krb5_db_get_key_data_kvno( krb5_context context, + int count, + krb5_key_data * data); + + +/* 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_kvno kvno, + krb5_keyblock *key, + char *master_pwd); + +krb5_error_code +krb5_def_store_mkey_list( krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd); + +krb5_error_code +krb5_db_def_fetch_mkey( krb5_context context, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args); + +krb5_error_code +krb5_def_verify_master_key( krb5_context context, + krb5_principal mprinc, + krb5_kvno kvno, + krb5_keyblock *mkey); + +krb5_error_code +krb5_def_fetch_mkey_list( krb5_context context, + krb5_principal mprinc, + const krb5_keyblock *mkey, + krb5_kvno mkvno, + krb5_keylist_node **mkeys_list); + +krb5_error_code kdb_def_set_mkey ( krb5_context kcontext, + char *pwd, + krb5_keyblock *key ); + +krb5_error_code kdb_def_set_mkey_list ( krb5_context kcontext, + krb5_keylist_node *keylist ); + +krb5_error_code kdb_def_get_mkey ( krb5_context kcontext, + krb5_keyblock **key ); + +krb5_error_code kdb_def_get_mkey_list ( krb5_context kcontext, + krb5_keylist_node **keylist ); + +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_dbekd_def_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_def_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_dbekd_def_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_def_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_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); + + +krb5_error_code +krb5_db_set_context + (krb5_context, void *db_context); + +krb5_error_code +krb5_db_get_context + (krb5_context, void **db_context); + +void +krb5_dbe_free_key_data_contents(krb5_context, krb5_key_data *); + +void +krb5_dbe_free_key_list(krb5_context, krb5_keylist_node *); + +void +krb5_dbe_free_actkvno_list(krb5_context, krb5_actkvno_node *); + +void +krb5_dbe_free_mkey_aux_list(krb5_context, krb5_mkey_aux_node *); + +void +krb5_dbe_free_tl_data(krb5_context, krb5_tl_data *); + +#define KRB5_KDB_DEF_FLAGS 0 + +#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_KDB_OPEN_RW 0 +#define KRB5_KDB_OPEN_RO 1 + +#define KRB5_KDB_OPT_SET_DB_NAME 0 +#define KRB5_KDB_OPT_SET_LOCK_MODE 1 + +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, + unsigned int flags, + 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 (*set_master_key_list) ( krb5_context kcontext, + krb5_keylist_node *keylist); + + krb5_error_code (*get_master_key_list) ( krb5_context kcontext, + krb5_keylist_node **keylist); + + 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_kvno kvno, + krb5_keyblock *key, + char *master_pwd); + + krb5_error_code (*fetch_master_key) ( krb5_context kcontext, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args); + + krb5_error_code (*verify_master_key) ( krb5_context kcontext, + krb5_principal mprinc, + krb5_kvno kvno, + krb5_keyblock *mkey ); + + krb5_error_code (*fetch_master_key_list) (krb5_context kcontext, + krb5_principal mname, + const krb5_keyblock *key, + krb5_kvno kvno, + krb5_keylist_node **mkeys_list); + + krb5_error_code (*store_master_key_list) ( krb5_context kcontext, + char *db_arg, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd); + + 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); + + krb5_error_code (*dbekd_decrypt_key_data) ( krb5_context kcontext, + const krb5_keyblock *mkey, + const krb5_key_data *key_data, + krb5_keyblock *dbkey, + krb5_keysalt *keysalt ); + + krb5_error_code (*dbekd_encrypt_key_data) ( krb5_context kcontext, + const krb5_keyblock *mkey, + const krb5_keyblock *dbkey, + const krb5_keysalt *keyselt, + int keyver, + krb5_key_data *key_data ); + + krb5_error_code + (*db_invoke) ( krb5_context context, + unsigned int method, + const krb5_data *req, + krb5_data *rep ); +} kdb_vftabl; +#endif /* !defined(_WIN32) */ + +#endif /* KRB5_KDB5__ */ diff --git a/krb5-1-7/src/include/kdb_ext.h b/krb5-1-7/src/include/kdb_ext.h new file mode 100644 index 000000000..59323e232 --- /dev/null +++ b/krb5-1-7/src/include/kdb_ext.h @@ -0,0 +1,169 @@ +/* + * include/krb5/kdb_ext.h + * + * Copyright (c) 2006-2008, 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 KRB5_KDB5_EXT__ +#define KRB5_KDB5_EXT__ + +/* Allowed to use protocol transition */ +#define KRB5_KDB_OK_TO_AUTH_AS_DELEGATE 0x00200000 +/* Service does not require authorization data */ +#define KRB5_KDB_NO_AUTH_DATA_REQUIRED 0x00400000 +/* Private flag used to indicate principal is local TGS */ +#define KRB5_KDB_TICKET_GRANTING_SERVICE 0x01000000 +/* Private flag used to indicate xrealm relationship is non-transitive */ +#define KRB5_KDB_XREALM_NON_TRANSITIVE 0x02000000 + +/* Entry get flags */ +/* Name canonicalization requested */ +#define KRB5_KDB_FLAG_CANONICALIZE 0x00000010 +/* Include authorization data generated by backend */ +#define KRB5_KDB_FLAG_INCLUDE_PAC 0x00000020 +/* Is AS-REQ (client referrals only) */ +#define KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY 0x00000040 +/* Map cross-realm principals */ +#define KRB5_KDB_FLAG_MAP_PRINCIPALS 0x00000080 +/* Protocol transition */ +#define KRB5_KDB_FLAG_PROTOCOL_TRANSITION 0x00000100 +/* Constrained delegation */ +#define KRB5_KDB_FLAG_CONSTRAINED_DELEGATION 0x00000200 +/* User-to-user */ +#define KRB5_KDB_FLAG_USER_TO_USER 0x00000800 +/* Cross-realm */ +#define KRB5_KDB_FLAG_CROSS_REALM 0x00001000 + +#define KRB5_KDB_FLAGS_S4U ( KRB5_KDB_FLAG_PROTOCOL_TRANSITION | \ + KRB5_KDB_FLAG_CONSTRAINED_DELEGATION ) + +#define KRB5_TL_PAC_LOGON_INFO 0x0100 /* NDR encoded validation info */ +#define KRB5_TL_SERVER_REFERRAL 0x0200 /* ASN.1 encoded ServerReferralInfo */ +#define KRB5_TL_SVR_REFERRAL_DATA 0x0300 /* ASN.1 encoded PA-SVR-REFERRAL-DATA */ +#define KRB5_TL_CONSTRAINED_DELEGATION_ACL 0x0400 /* Each entry is a permitted SPN */ +#define KRB5_TL_LM_KEY 0x0500 /* LM OWF */ +#define KRB5_TL_X509_SUBJECT_ISSUER_NAME 0x0600 /* IssuerDNSubjectDN */ + +krb5_error_code krb5_db_get_principal_ext ( krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry *entries, + int *nentries, + krb5_boolean *more ); + +krb5_error_code krb5_db_invoke ( krb5_context kcontext, + unsigned int method, + const krb5_data *req, + krb5_data *rep ); + +/* db_invoke methods */ +#define KRB5_KDB_METHOD_SIGN_AUTH_DATA 0x00000010 +#define KRB5_KDB_METHOD_CHECK_TRANSITED_REALMS 0x00000020 +#define KRB5_KDB_METHOD_CHECK_POLICY_AS 0x00000030 +#define KRB5_KDB_METHOD_CHECK_POLICY_TGS 0x00000040 +#define KRB5_KDB_METHOD_AUDIT_AS 0x00000050 +#define KRB5_KDB_METHOD_AUDIT_TGS 0x00000060 +#define KRB5_KDB_METHOD_REFRESH_POLICY 0x00000070 +#define KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE 0x00000080 + +typedef struct _kdb_sign_auth_data_req { + krb5_magic magic; + unsigned int flags; /* KRB5_KDB flags */ + krb5_const_principal client_princ; /* Client name used in ticket */ + krb5_db_entry *client; /* DB entry for client principal */ + krb5_db_entry *server; /* DB entry for server principal */ + krb5_db_entry *krbtgt; /* DB entry for ticket granting service principal */ + krb5_keyblock *client_key; /* Reply key, valid for AS-REQ only */ + krb5_keyblock *server_key; /* Key used to generate server signature */ + krb5_timestamp authtime; /* Authtime of TGT */ + krb5_authdata **auth_data; /* Authorization data from TGT */ +} kdb_sign_auth_data_req; + +typedef struct _kdb_sign_auth_data_rep { + krb5_magic magic; + krb5_authdata **auth_data; /* Signed authorization data */ + krb5_db_entry *entry; /* Optional client principal extracted from auth data */ + int nprincs; /* Non-zero if above contains principal data */ +} kdb_sign_auth_data_rep; + +typedef struct _kdb_check_transited_realms_req { + krb5_magic magic; + const krb5_data *tr_contents; + const krb5_data *client_realm; + const krb5_data *server_realm; +} kdb_check_transited_realms_req; + +typedef struct _kdb_check_policy_as_req { + krb5_magic magic; + krb5_kdc_req *request; + krb5_db_entry *client; + krb5_db_entry *server; + krb5_timestamp kdc_time; +} kdb_check_policy_as_req; + +typedef struct _kdb_check_policy_as_rep { + krb5_magic magic; + const char *status; +} kdb_check_policy_as_rep; + +typedef struct _kdb_check_policy_tgs_req { + krb5_magic magic; + krb5_kdc_req *request; + krb5_db_entry *server; + krb5_ticket *ticket; +} kdb_check_policy_tgs_req; + +typedef struct _kdb_check_policy_tgs_rep { + krb5_magic magic; + const char *status; +} kdb_check_policy_tgs_rep; + +typedef struct _kdb_audit_as_req { + krb5_magic magic; + krb5_kdc_req *request; + krb5_db_entry *client; + krb5_db_entry *server; + krb5_timestamp authtime; + krb5_error_code error_code; +} kdb_audit_as_req; + +typedef struct _kdb_audit_tgs_req { + krb5_magic magic; + krb5_kdc_req *request; + krb5_const_principal client; + krb5_db_entry *server; + krb5_timestamp authtime; + krb5_error_code error_code; +} kdb_audit_tgs_req; + +typedef struct _kdb_check_allowed_to_delegate_req { + krb5_magic magic; + const krb5_db_entry *server; + krb5_const_principal proxy; +} kdb_check_allowed_to_delegate_req; + +#endif /* KRB5_KDB5_EXT__ */ diff --git a/krb5-1-7/src/include/kdb_kt.h b/krb5-1-7/src/include/kdb_kt.h new file mode 100644 index 000000000..1dbd7f30d --- /dev/null +++ b/krb5-1-7/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-7/src/include/kdb_log.h b/krb5-1-7/src/include/kdb_log.h new file mode 100644 index 000000000..804b7328a --- /dev/null +++ b/krb5-1-7/src/include/kdb_log.h @@ -0,0 +1,124 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _KDB_LOG_H +#define _KDB_LOG_H + +/* #pragma ident "@(#)kdb_log.h 1.3 04/02/23 SMI" */ + +#include +#include +#include +#include "kdb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DB macros + */ +#define INDEX(ulogaddr, i) ((unsigned long) ulogaddr + sizeof (kdb_hlog_t) + \ + (i*ulog->kdb_block)) + +/* + * Current DB version # + */ +#define KDB_VERSION 1 + +/* + * DB log states + */ +#define KDB_STABLE 1 +#define KDB_UNSTABLE 2 +#define KDB_CORRUPT 3 + +/* + * DB log constants + */ +#define KDB_ULOG_MAGIC 0x6661212 +#define KDB_ULOG_HDR_MAGIC 0x6662323 + +/* + * DB Flags + */ +#define FKADMIND 1 +#define FKPROPLOG 2 +#define FKPROPD 3 +#define FKCOMMAND 4 /* Includes kadmin.local and kdb5_util */ + +/* + * Default ulog file attributes + */ +#define MAX_ULOGENTRIES 2500 +#define DEF_ULOGENTRIES 1000 +#define ULOG_IDLE_TIME 10 /* in seconds */ +/* + * Max size of update entry + update header + * We make this large since resizing can be costly. + */ +#define ULOG_BLOCK 2048 /* Default size of principal record */ + +#define MAXLOGLEN 0x10000000 /* 256 MB log file */ + +/* + * Prototype declarations + */ +extern krb5_error_code ulog_map(krb5_context context, + const char *logname, uint32_t entries, + int caller, + char **db_args); +extern krb5_error_code ulog_add_update(krb5_context context, + kdb_incr_update_t *upd); +extern krb5_error_code ulog_delete_update(krb5_context context, + kdb_incr_update_t *upd); +extern krb5_error_code ulog_finish_update(krb5_context context, + kdb_incr_update_t *upd); +extern krb5_error_code ulog_get_entries(krb5_context context, kdb_last_t last, + kdb_incr_result_t *ulog_handle); +extern krb5_error_code ulog_replay(krb5_context context, + kdb_incr_result_t *incr_ret, char **db_args); +extern krb5_error_code ulog_conv_2logentry(krb5_context context, + krb5_db_entry *entries, kdb_incr_update_t *updates, int nentries); +extern krb5_error_code ulog_conv_2dbentry(krb5_context context, + krb5_db_entry *entries, kdb_incr_update_t *updates, int nentries); +extern void ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates); +extern krb5_error_code ulog_set_role(krb5_context ctx, iprop_role role); + +extern krb5_error_code ulog_lock(krb5_context ctx, int mode); + +typedef struct kdb_hlog { + uint32_t kdb_hmagic; /* Log header magic # */ + uint16_t db_version_num; /* Kerberos database version no. */ + uint32_t kdb_num; /* # of updates in log */ + kdbe_time_t kdb_first_time; /* Timestamp of first update */ + kdbe_time_t kdb_last_time; /* Timestamp of last update */ + kdb_sno_t kdb_first_sno; /* First serial # in the update log */ + kdb_sno_t kdb_last_sno; /* Last serial # in the update log */ + uint16_t kdb_state; /* State of update log */ + uint16_t kdb_block; /* Block size of each element */ +} kdb_hlog_t; + +typedef struct kdb_ent_header { + uint32_t kdb_umagic; /* Update entry magic # */ + kdb_sno_t kdb_entry_sno; /* Serial # of entry */ + kdbe_time_t kdb_time; /* Timestamp of update */ + bool_t kdb_commit; /* Is the entry committed or not */ + uint32_t kdb_entry_size; /* Size of update entry */ + uint8_t entry_data[4]; /* Address of kdb_incr_update_t */ +} kdb_ent_header_t; + +typedef struct _kdb_log_context { + iprop_role iproprole; + kdb_hlog_t *ulog; + uint32_t ulogentries; + int ulogfd; +} kdb_log_context; + +#ifdef __cplusplus +} +#endif + +#endif /* !_KDB_LOG_H */ diff --git a/krb5-1-7/src/include/kim/kim.h b/krb5-1-7/src/include/kim/kim.h new file mode 100644 index 000000000..050e01b03 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim.h @@ -0,0 +1,169 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_H +#define KIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! + * \mainpage Kerberos Identity Management (KIM) API Documentation + * + * \section introduction Introduction + * + * The Kerberos Identity Management API is a high level API for managing the selection + * and management of Kerberos credentials. It is intended for use by applications, + * credential management applications (eg: kinit, kpasswd, etc) and internally by the + * Kerberos libraries. Under some circumstances client applications may also benefit + * from the Kerberos Identity Management API. + * + * + * \section conventions API Conventions + * + * Although KIM currently only provides a C API, it attempts to make that API as + * object-oriented as possible. KIM functions are grouped by object and all of the + * object types are opaque, including errors. The reason for this is two-fold. First, + * the KIM API is rather large. Grouping functions by object allows the API to be + * broken up into smaller, more manageable chunks. Second, providing an object-like C + * API will make it easier to port to object oriented languages. + * + * Because C lacks classes and other object oriented syntax, KIM functions adhere to + * the following naming conventions to make functions easier to identify: + * + * \li Functions beginning with \b kim_object_create are constructors for an object of + * type kim_object. On success these functions return a newly allocated object which + * must later be freed by the caller. + * + * \li Functions of the form \b kim_object_copy are copy constructors. They instantiate + * a new object of kim_object from an object of the same type. + * + * \li Functions of the form \b kim_object_free are destructors for objects of type + * kim_object. + * + * \li Functions beginning with \b kim_object_get and \b kim_object_set + * examine and modify properties of objects of type kim_object. + * + * \li All KIM APIs except destructors and error management APIs return a + * KIM Error object (kim_error_t). + * + * + * \section terminology Terminology + * + * Kerberos organizes its authentication tokens by client identity (the name of the user) + * and service identity (the name of a service). The following terms are used throughout + * this documentation: + * + * \li credential - A token which authenticates a client identity to a + * service identity. + * + * \li ccache - Short for "credentials cache". A set of credentials for a single + * client identity. + * + * \li cache collection - The set of all credential caches. + * + * \li default ccache - A credentials cache that the Kerberos libraries will use + * if no ccache is specified by the caller. Use of the default + * ccache is now discouraged. Instead applications should use + * selection hints to choose an appropriate client identity. + * + * \section selection_api Client Identity Selection APIs + * + * KIM provides high level APIs for applications to select which client identity to + * use. Use of these APIs is intended to replace the traditional "default ccache" + * mechanism previously used by Kerberos. + * + * KIM Selection Hints (kim_selection_hints_t) controls options for selecting + * a client identity: + * - \subpage kim_selection_hints_overview + * - \subpage kim_selection_hints_reference + * + * KIM Identity (kim_identity_t) provides an immutable Kerberos identity object + * - \subpage kim_identity_overview + * - \subpage kim_identity_reference + * + * + * \section management_api Credential Management APIs + * + * KIM also provides APIs for acquiring new credentials over the network + * by contacting a KDC and for viewing and modifying the existing credentials + * in the cache collection + * + * Whether or not you use the credential or ccache APIs depends on + * whether you want KIM to store any newly acquired credentials in the + * cache collection. KIM ccache APIs always create a ccache in the cache + * collection containing newly acquired credentials whereas the KIM + * credential APIs just return a credential object. In general most + * callers want to store newly acquired credentials and should use the + * KIM ccache APIs when acquiring credentials. + * + * KIM CCache (kim_ccache_t) manipulates credential caches in the cache collection: + * - \subpage kim_ccache_overview + * - \subpage kim_ccache_reference + * + * KIM Credential (kim_credential_t) manipulates credentials: + * - \subpage kim_credential_overview + * - \subpage kim_credential_reference + * + * KIM Options (kim_options_t) control options for credential acquisition: + * - \subpage kim_options_overview + * - \subpage kim_options_reference + * + * KIM Preferences (kim_preferences_t) views and edits the current user's preferences: + * - \subpage kim_preferences_overview + * - \subpage kim_preferences_reference + * + * + * \section utility_apis Miscellaneous APIs + * + * The high and low level APIs depend on the following basic utility classes + * to manage generic types. + * + * KIM String (kim_string_t) provides memory management for an immutable string: + * - \subpage kim_string_overview + * - \subpage kim_string_reference + * + * + * + * \section types Types and Constants + * + * \li \subpage kim_types_reference + */ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_H */ diff --git a/krb5-1-7/src/include/kim/kim_ccache.h b/krb5-1-7/src/include/kim/kim_ccache.h new file mode 100644 index 000000000..a1cba1710 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_ccache.h @@ -0,0 +1,659 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_CCACHE_H +#define KIM_CCACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + * \page kim_ccache_overview KIM CCache Overview + * + * \section kim_ccache_introduction Introduction + * + * Kerberos credentials are stored in "ccaches" (short for "credentials caches"). + * The set of all ccaches which the KIM can use is called the "cache collection". + * Each ccache has a name and type which uniquely identify it in the cache + * collection and a client identity. The ccache's client identity is the + * identity whose credentials are stored in the ccache. This allows for easy + * lookup of all the credentials for a given identity. + * + * KIM attempts to preserve a one-to-one relationship between client identities + * and ccaches. If the KIM is used to manipulate the cache collection, there + * will be one ccache per identity. However, because low-level APIs allow callers + * to create multiple ccaches for the same client identity or a single ccache + * containing credentials for different client identities, KIM handles those + * situations. In general when searching KIM will find the first ccache matching + * the requested client identity. It will not find credentials for the requested + * client identity if they are in a ccache with a different client identity. + * + * The kim_ccache_t object is a reference to a ccache in the cache collection. + * If other applications make changes to the the ccache pointed to by a KIM ccache + * object, the object will immediately show those changes. KIM performs locking + * on the cache collection to prevent deadlocks and maintain a consistent behavior + * when multiple applications attempt to modify the cache collection. + * + * \note KIM ccache APIs are intended for applications and system + * tools which manage credentials for the user. They are not a substitute for + * krb5 and GSSAPI functions which obtain service credentials for the purpose + * of authenticating a client to an application server. + * + * \section kim_credential_cache_collection Acquiring a CCache from the Cache Collection + * + * KIM provides a simple iterator API for iterating over the ccaches + * in the cache collection. First, call #kim_ccache_iterator_create() to obtain + * an iterator for the cache collection. Then loop calling + * #kim_ccache_iterator_next() until either you find the ccache you are looking + * for or the API returns a NULL ccache, indicating that there are no more + * ccaches in the cache collection. When you are done with the iterator, call + * #kim_ccache_iterator_free(). + * + * \note #kim_ccache_iterator_next() returns ccache objects which + * must be freed with #kim_ccache_free() to avoid leaking memory. + * + * KIM also provides a convenient API #kim_ccache_create_from_client_identity() + * which returns the ccache for a specific client identity, if any exists. + * Typically callers of this API obtain the client identity using + * #kim_selection_hints_get_identity(). + * + * + * \section kim_ccache_acquire_default Acquiring Credentials from the Default CCache + * + * #kim_ccache_create_from_default() returns the default ccache. + * The default ccache is a legacy concept which was replaced by selection + * hints. Prior to the existence of selection hints, applications always + * looked at the default ccache for credentials. By setting the system default + * ccache, users could manually control which credentials each application used. + * As the number of ccaches and applications has grown, this mechanism has become + * unusable. You should avoid using this API whenever possible. + * + * + * \section kim_ccache_acquire_new Acquiring New Credentials in a CCache + * + * KIM provides the #kim_ccache_create_new() API for acquiring new + * credentials and storing them in a ccache. Credentials can either be + * obtained for a specific client identity or by specifying + * #KIM_IDENTITY_ANY to allow the user to choose. Typically + * callers of this API obtain the client identity using + * #kim_selection_hints_get_identity(). Depending on the kim_options + * specified, #kim_ccache_create_new() may present a GUI or command line + * prompt to obtain information from the user. + * + * #kim_ccache_create_new_if_needed() + * searches the cache collection for a ccache for the client identity + * and if no appropriate ccache is available, attempts to acquire + * new credentials and store them in a new ccache. Depending on the + * kim_options specified, #kim_ccache_create_new_if_needed() may + * present a GUI or command line prompt to obtain information from the + * user. This function exists for convenience and to avoid code duplication. + * It can be trivially implemented using + * #kim_ccache_create_from_client_identity() and #kim_ccache_create_new(). + * + * For legacy password-based Kerberos environments KIM also provides + * #kim_ccache_create_new_with_password() and + * #kim_ccache_create_new_if_needed_with_password(). You should not use these + * functions unless you know that they will only be used in environments using + * passwords. Otherwise users without passwords may be prompted for them. + * + * KIM provides the #kim_ccache_create_from_keytab() to create credentials + * using a keytab and store them in the cache collection. A keytab is an + * on-disk copy of a client identity's secret key. Typically sites use + * keytabs for client identities that identify a machine or service and + * protect the keytab with disk permissions. Because a keytab is + * sufficient to obtain credentials, keytabs will normally only be readable + * by root, Administrator or some other privileged account. + * Typically applications use credentials obtained from keytabs to obtain + * credentials for batch processes. These keytabs and credentials are usually + * for a special identity used for the batch process rather than a user + * identity. + * + * + * \section kim_ccache_validate Validating Credentials in a CCache + * + * A credential with a start time in the future (ie: after the issue date) + * is called a post-dated credential. Because the KDC administrator may + * wish to disable a identity, once the start time is reached, all post-dated + * credentials must be validated before they can be used. Otherwise an + * attacker using a compromised account could acquire lots of post-dated + * credentials to circumvent the acccount being disabled. + * + * KIM provides the #kim_ccache_validate() API to validate the TGT + * credential in a ccache. Note that this API replaces any existing + * credentials with the validated credential. + * + * + * \section kim_ccache_renew Renewing Credentials in a CCache + * + * A renewable credential can be used to obtain a new identical credential + * without resending secret information (such as a password) to the KDC. + * A credential may only be renewed during its renewal lifetime and while + * valid. + * + * KIM provides the #kim_ccache_renew() API to renew the TGT credential + * in a ccache. Note that this API replaces any existing credentials with the + * renewed credential. + * + * + * \section kim_ccache_verify Verifying Credentials in a CCache + * + * When a program acquires TGT credentials for the purpose of authenticating + * itself to the machine it is running on, it is insufficient for the machine + * to assume that the caller is authorized just because it got credentials. + * Instead, the credentials must be verified using a key the local machine. + * The reason this is necessary is because an attacker can trick the + * machine into obtaining credentials from any KDC, including malicious ones + * with the same realm name as the local machine's realm. This exploit is + * called the Zanarotti attack. + * + * In order to avoid the Zanarotti attack, the local machine must authenticate + * the process in the same way an application server would authenticate a client. + * Like an application server, the local machine must have its own identity in + * its realm and a keytab for that identity on its local disk. However, + * rather than forcing system daemons to use the network-oriented calls in the + * krb5 and GSS APIs, KIM provides the #kim_ccache_verify() API to + * verify credentials directly. + * + * The most common reason for using #kim_ccache_verify() is user login. + * If the local machine wants to use Kerberos to verify the username and password + * provided by the user, it must call #kim_ccache_verify() on the credentials + * it obtains to make sure they are really from a KDC it trusts. Another common + * case is a server which is only using Kerberos internally. For example an + * LDAP or web server might use a username and password obtained over the network + * to get Kerberos credentials. In order to make sure they aren't being tricked + * into talking to the wrong KDC, these servers must also call + * #kim_ccache_verify(). + * + * The Zanarotti attack is only a concern if the act of accessing the machine + * gives the process special access. Thus a managed cluster machine with + * Kerberos-authenticated networked home directories does not need to call + * #kim_ccache_verify(). Even though an attacker can log in as any user on + * the cluster machine, the attacker can't actually access any of the user's data + * or use any of their privileges because those are all authenticated via + * Kerberized application servers (and thus require actually having credentials + * for the real local realm). + * + * #kim_ccache_verify() provides an option to + * return success even if the machine's host key is not present. This option + * exists for sites which have a mix of different machines, some of which are + * vulnerable to the Zanarotti attack and some are not. If this option is used, + * it is the responsiblity of the machine's maintainer to obtain a keytab + * for their machine if it needs one. + * + * + * \section kim_ccache_properties Examining CCache Properties + * + * \li #kim_ccache_get_type() returns the type of the ccache. Types include + * "API" for CCAPI ccaches, "FILE" for file-based ccaches and "MEMORY" for + * single-process in-memory ccaches. + * + * \li #kim_ccache_get_name() returns the name of the ccache. A ccache's name + * identifies the ccache uniquely among ccaches of the same type. Note that + * two ccaches with different types may have the same name. + * + * \li #kim_ccache_get_display_name() returns a display string which uniquely + * identifies a ccache. A ccache display name is of the form ":" + * and can be displayed to the user or used as an argument to certain krb5 + * APIs, such as krb5_cc_resolve(). + * + * \li #kim_ccache_get_client_identity() + * returns the ccache's client identity. + * + * \li #kim_ccache_get_valid_credential() + * returns the first valid TGT in the ccache for its client identity. + * If there are no TGTs in the ccache, it returns the first + * valid non-TGT credential for the ccache's client identity. + * TGT credentials (ie: "ticket-granting tickets") are credentials for + * the krbtgt service: a service identity of the form "krbtgt/@". + * These credentials allow the entity named by the client identity to obtain + * additional credentials without resending shared secrets (such as a password) + * to the KDC. Kerberos uses TGTs to provide single sign-on authentication. + * + * \li #kim_ccache_get_start_time() + * returns when the credential's in a ccache will become valid. + * Credentials may be "post-dated" which means that their lifetime starts sometime + * in the future. Note that when a post-dated credential's start time is reached, + * the credential must be validated. See \ref kim_credential_validate for more information. + * + * \li #kim_ccache_get_expiration_time() + * returns when the credential's in a ccache will expire. + * Credentials are time limited by the lifetime of the credential. While you can + * request a credential of any lifetime, the KDC limits the credential lifetime + * to a administrator-defined maximum. Typically credential lifetime range from 10 + * to 21 hours. + * + * \li #kim_ccache_get_renewal_expiration_time() + * returns when the credential's in a ccache will no longer be renewable. + * Valid credentials may be renewed up until their renewal expiration time. + * Renewing credentials acquires a fresh set of credentials with a full lifetime + * without resending secrets to the KDC (such as a password). If credentials are + * not renewable, this function will return an error. + * + * \li #kim_ccache_get_options() + * returns a kim_options object with the credential options of the credentials + * in the ccache. This function is intended to be used when adding + * an identity with existing credentials to the favorite identities list. + * By passing in the options returned by this call, future requests for the + * favorite identity will use the same credential options. + * + * See \ref kim_ccache_reference and \ref kim_ccache_iterator_reference for + * information on specific APIs. + */ + + +/*! + * \defgroup kim_ccache_iterator_reference KIM CCache Iterator Reference Documentation + * @{ + */ + +/*! + * \param out_ccache_iterator on exit, a ccache iterator object for the cache collection. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a ccache iterator to enumerate ccaches in the cache collection. + */ +kim_error kim_ccache_iterator_create (kim_ccache_iterator *out_ccache_iterator); + +/*! + * \param in_ccache_iterator a ccache iterator object. + * \param out_ccache on exit, the next ccache in the cache collection. If there are + * no more ccaches in the cache collection this argument will be + * set to NULL. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the next ccache in the cache collection. + */ +kim_error kim_ccache_iterator_next (kim_ccache_iterator in_ccache_iterator, + kim_ccache *out_ccache); + +/*! + * \param io_ccache_iterator a ccache iterator object to be freed. Set to NULL on exit. + * \brief Free memory associated with a ccache iterator. + */ +void kim_ccache_iterator_free (kim_ccache_iterator *io_ccache_iterator); + +/*!@}*/ + +/*! + * \defgroup kim_ccache_reference KIM CCache Reference Documentation + * @{ + */ + +/*! + * \param out_ccache on exit, a new cache object for a ccache containing a newly acquired + * initial credential. Must be freed with kim_ccache_free(). + * \param in_client_identity a client identity to obtain a credential for. Specify KIM_IDENTITY_ANY to + * allow the user to choose. + * \param in_options options to control credential acquisition. + * \note #kim_ccache_create_new() may + * present a GUI or command line prompt to obtain information from the user. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential and store it in a ccache. + */ +kim_error kim_ccache_create_new (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options); + +/*! + * \param out_ccache on exit, a new cache object for a ccache containing a newly acquired + * initial credential. Must be freed with kim_ccache_free(). + * \param in_client_identity a client identity to obtain a credential for. Specify KIM_IDENTITY_ANY to + * allow the user to choose. + * \param in_options options to control credential acquisition. + * \param in_password a password to be used while obtaining credentials. + * \note #kim_ccache_create_new_with_password() exists to support + * legacy password-based Kerberos environments. You should not use this + * function unless you know that it will only be used in environments using passwords. + * This function may also present a GUI or command line prompt to obtain + * additional information needed to obtain credentials (eg: SecurID pin). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential and store it in a ccache + * using the provided password.. + */ +kim_error kim_ccache_create_new_with_password (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options, + kim_string in_password); + +/*! + * \param out_ccache on exit, a ccache object for a ccache containing a newly acquired + * initial credential. Must be freed with kim_ccache_free(). + * \param in_client_identity a client identity to obtain a credential for. + * \param in_options options to control credential acquisition (if a credential is acquired). + * \note #kim_ccache_create_new_if_needed() may + * present a GUI or command line prompt to obtain information from the user. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Find a ccache containing a valid initial credential in the cache collection, or if + * unavailable, acquire and store a new initial credential. + */ +kim_error kim_ccache_create_new_if_needed (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options); + +/*! + * \param out_ccache on exit, a ccache object for a ccache containing a newly acquired + * initial credential. Must be freed with kim_ccache_free(). + * \param in_client_identity a client identity to obtain a credential for. + * \param in_options options to control credential acquisition (if a credential is acquired). + * \param in_password a password to be used while obtaining credentials. + * \note #kim_ccache_create_new_if_needed_with_password() exists to support + * legacy password-based Kerberos environments. You should not use this + * function unless you know that it will only be used in environments using passwords. + * This function may also present a GUI or command line prompt to obtain + * additional information needed to obtain credentials (eg: SecurID pin). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Find a ccache containing a valid initial credential in the cache collection, or if + * unavailable, acquire and store a new initial credential using the provided password. + */ +kim_error kim_ccache_create_new_if_needed_with_password (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options, + kim_string in_password); + +/*! + * \param out_ccache on exit, a ccache object for a ccache containing a TGT + * credential. Must be freed with kim_ccache_free(). + * \param in_client_identity a client identity to find a ccache for. If + * \a in_client_identity is #KIM_IDENTITY_ANY, this + * function returns the default ccache + * (ie: is equivalent to #kim_ccache_create_from_default()). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Find a ccache for a client identity in the cache collection. + */ +kim_error kim_ccache_create_from_client_identity (kim_ccache *out_ccache, + kim_identity in_client_identity); + +/*! + * \param out_ccache on exit, a new ccache object containing an initial credential + * for the client identity \a in_identity obtained using in_keytab. + * Must be freed with kim_ccache_free(). + * \param in_identity a client identity to obtain a credential for. Specify NULL for + * the first client identity in the keytab. + * \param in_options options to control credential acquisition. + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential from a keytab and store it in a ccache. + */ +kim_error kim_ccache_create_from_keytab (kim_ccache *out_ccache, + kim_identity in_identity, + kim_options in_options, + kim_string in_keytab); + +/*! + * \param out_ccache on exit, a ccache object for the default ccache. + * Must be freed with kim_ccache_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the default ccache. + */ +kim_error kim_ccache_create_from_default (kim_ccache *out_ccache); + +/*! + * \param out_ccache on exit, a ccache object for the ccache identified by + * \a in_display_name. Must be freed with kim_ccache_free(). + * \param in_display_name a ccache display name string (ie: "TYPE:NAME"). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This API is used to obtain a kim_ccache for a ccache name entered by the user. + * \brief Get a ccache for a ccache display name. + */ +kim_error kim_ccache_create_from_display_name (kim_ccache *out_ccache, + kim_string in_display_name); + +/*! + * \param out_ccache on exit, a ccache object for the ccache identified by + * \a in_type and \a in_name. Must be freed with kim_ccache_free(). + * \param in_type a ccache type string. + * \param in_name a ccache name string. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This API is provided for backwards compatibilty with applications which are not + * KIM-aware and should be avoided whenever possible. + * \brief Get a ccache for a ccache type and name. + */ +kim_error kim_ccache_create_from_type_and_name (kim_ccache *out_ccache, + kim_string in_type, + kim_string in_name); + +/*! + * \param out_ccache on exit, a new ccache object which is a copy of in_krb5_ccache. + * Must be freed with kim_ccache_free(). + * \param in_krb5_context the krb5 context used to create \a in_krb5_ccache. + * \param in_krb5_ccache a krb5 ccache object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a ccache for a krb5 ccache. + */ +kim_error kim_ccache_create_from_krb5_ccache (kim_ccache *out_ccache, + krb5_context in_krb5_context, + krb5_ccache in_krb5_ccache); + +/*! + * \param out_ccache on exit, the new ccache object which is a copy of in_ccache. + * Must be freed with kim_ccache_free(). + * \param in_ccache a ccache object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a ccache. + */ +kim_error kim_ccache_copy (kim_ccache *out_ccache, + kim_ccache in_ccache); + +/*! + * \param in_ccache a ccache object. + * \param in_compare_to_ccache a ccache object. + * \param out_comparison on exit, a comparison of \a in_ccache and + * \a in_compare_to_ccache which determines whether + * or not the two ccache objects refer to the same ccache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Compare ccache objects. + */ +kim_error kim_ccache_compare (kim_ccache in_ccache, + kim_ccache in_compare_to_ccache, + kim_comparison *out_comparison); + +/*! + * \param in_ccache a ccache object. + * \param in_krb5_context a krb5 context which will be used to create out_krb5_ccache. + * \param out_krb5_ccache on exit, a new krb5 ccache object which is a copy of in_ccache. + * Must be freed with krb5_cc_close() or krb5_cc_destroy(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a krb5 ccache for a ccache. + */ +kim_error kim_ccache_get_krb5_ccache (kim_ccache in_ccache, + krb5_context in_krb5_context, + krb5_ccache *out_krb5_ccache); + +/*! + * \param in_ccache a ccache object. + * \param out_name on exit, the name string of \a in_ccache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the name of a ccache. + */ +kim_error kim_ccache_get_name (kim_ccache in_ccache, + kim_string *out_name); + +/*! + * \param in_ccache a ccache object. + * \param out_type on exit, the type string of \a in_ccache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the type of a ccache. + */ +kim_error kim_ccache_get_type (kim_ccache in_ccache, + kim_string *out_type); + +/*! + * \param in_ccache a ccache object. + * \param out_display_name on exit, the type and name of \a in_ccache in a format appropriate for + * display to the user in command line programs. (ie: ":") + * Must be freed with kim_string_free(). + * Note: this string can also be passed to krb5_cc_resolve(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the type and name for a ccache in display format. + */ +kim_error kim_ccache_get_display_name (kim_ccache in_ccache, + kim_string *out_display_name); + +/*! + * \param in_ccache a ccache object. + * \param out_client_identity on exit, an identity object containing the client identity of + * \a in_ccache. Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the client identity for a ccache. + */ +kim_error kim_ccache_get_client_identity (kim_ccache in_ccache, + kim_identity *out_client_identity); + +/*! + * \param in_ccache a ccache object. + * \param out_credential on exit, the first valid credential in \a in_ccache. + * Must be freed with kim_credential_free(). Set to NULL + * if you only want return value, not the actual credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the first valid credential in a ccache. + * \note This function prefers valid TGT credentials. If there are only non-valid TGTs + * in the ccache, it will always return an error. However, if there are no + * TGTs at all, it will return the first valid non-TGT credential. If you only want + * TGTs, use kim_credential_is_tgt() to verify that \a out_credential is a tgt. + */ +kim_error kim_ccache_get_valid_credential (kim_ccache in_ccache, + kim_credential *out_credential); + +/*! + * \param in_ccache a ccache object. + * \param out_state on exit, the state of the credentials in \a in_ccache. + * See #kim_credential_state_enum for the possible values + * of \a out_state. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Check the state of the credentials in a ccache (valid, expired, postdated, etc). + * \note This function prefers TGT credentials. If there are any TGTs in the + * ccache, it will always return their state. However, if there are no + * TGTs at all, it will return the state of the first non-TGT credential. + */ +kim_error kim_ccache_get_state (kim_ccache in_ccache, + kim_credential_state *out_state); + +/*! + * \param in_ccache a ccache object. + * \param out_start_time on exit, the time when the credentials in \a in_ccache + * become valid. May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials in the ccache become valid. + */ +kim_error kim_ccache_get_start_time (kim_ccache in_ccache, + kim_time *out_start_time); + +/*! + * \param in_ccache a ccache object. + * \param out_expiration_time on exit, the time when the credentials in + * \a in_ccache will expire. May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials in the ccache will expire. + */ +kim_error kim_ccache_get_expiration_time (kim_ccache in_ccache, + kim_time *out_expiration_time); + +/*! + * \param in_ccache a ccache object. + * \param out_renewal_expiration_time on exit, the time when the credentials in \a in_ccache + * will no longer be renewable. May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials in the ccache will no longer be renewable. + */ +kim_error kim_ccache_get_renewal_expiration_time (kim_ccache in_ccache, + kim_time *out_renewal_expiration_time); + +/*! + * \param in_ccache a ccache object. + * \param out_options on exit, an options object reflecting the ticket + * options of the credentials in \a in_ccache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a kim_options object based on a ccache's credential attributes. + */ +kim_error kim_ccache_get_options (kim_ccache in_ccache, + kim_options *out_options); + +/*! + * \param io_ccache a ccache object which will be set to the default ccache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This API is provided for backwards compatibilty with applications which are not + * KIM-aware and should be avoided whenever possible. + * \brief Set a ccache to the default ccache. + */ +kim_error kim_ccache_set_default (kim_ccache io_ccache); + +/*! + * \param in_ccache a ccache object containing the TGT credential to be verified. + * \param in_service_identity a service identity to look for in the keytab. Specify + * KIM_IDENTITY_ANY to use the default service identity + * (usually host/@). + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \param in_fail_if_no_service_key whether or not the absence of a key for \a in_service_identity + * in the host's keytab will cause a failure. + * \note specifying FALSE for \a in_fail_if_no_service_key may expose the calling program to + * the Zanarotti attack if the host has no keytab installed. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Verify the TGT in a ccache. + */ +kim_error kim_ccache_verify (kim_ccache in_ccache, + kim_identity in_service_identity, + kim_string in_keytab, + kim_boolean in_fail_if_no_service_key); + +/*! + * \param in_ccache a ccache object containing a TGT to be renewed. + * \param in_options initial credential options to be used if a new credential is obtained. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Renew the TGT in a ccache. + */ +kim_error kim_ccache_renew (kim_ccache in_ccache, + kim_options in_options); + +/*! + * \param in_ccache a ccache object containing a TGT to be validated. + * \param in_options initial credential options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Validate the TGT in a ccache. + */ +kim_error kim_ccache_validate (kim_ccache in_ccache, + kim_options in_options); + +/*! + * \param io_ccache a ccache object to be destroyed. Set to NULL on exit. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Remove a ccache from the cache collection. + * \note Frees memory associated with the ccache. Do not call kim_ccache_free() + * after calling this function. + */ +kim_error kim_ccache_destroy (kim_ccache *io_ccache); + +/*! + * \param io_ccache a ccache object to be freed. Set to NULL on exit. + * \brief Free memory associated with a ccache. + */ +void kim_ccache_free (kim_ccache *io_ccache); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_CCACHE_H */ diff --git a/krb5-1-7/src/include/kim/kim_credential.h b/krb5-1-7/src/include/kim/kim_credential.h new file mode 100644 index 000000000..c061f1199 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_credential.h @@ -0,0 +1,568 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_CREDENTIAL_H +#define KIM_CREDENTIAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/*! + * \addtogroup kim_types_reference + * @{ + */ + +/*! + * Possible credential states. Credentials may be: + * \li valid - The credential can be used. + * \li expired - The credential's lifetime has been exceeded. + * \li not_yet_valid - The credential is post dated and the time when + * it becomes valid has not yet been reached. + * \li needs_validation - The credential is post-dated and although + * the time when it becomes valid has been reached + * it has not yet been validated. + * \li address_mismatch - The credential contains IP address(es) which do + * not match the host's local address(es). + */ +enum kim_credential_state_enum { + kim_credentials_state_valid = 0, + kim_credentials_state_expired = 1, + kim_credentials_state_not_yet_valid = 2, + kim_credentials_state_needs_validation = 3, + kim_credentials_state_address_mismatch = 4 +}; + +/*! + * The state of a credential. See #kim_credential_state_enum for + * possible values. + */ +typedef int kim_credential_state; + +/*! @} */ + +/*! + * \page kim_credential_overview KIM Credential Overview + * + * \section kim_credential_introduction Introduction + * + * A Kerberos credential (also called a "Kerberos ticket") is a time-limited + * token issued by a KDC which authenticates the entity named by the credential's + * client identity to the service named by the credential's service identity. + * + * The kim_credential object contains a single Kerberos credential. KIM credentials + * objects are always copies of credentials, not references to credentials + * stored in the cache collection. Modifying credential objects in the ccache + * collection will not change any existing KIM credential objects. + * + * KIM credential APIs are intended for applications and system + * tools which manage credentials for the user. They are not a substitute for + * krb5 and GSSAPI functions which obtain service credentials for the purpose + * of authenticating a client to an application server. + * + * \note Many of the APIs listed below have equivalent functions which + * operate on ccaches. In most cases applications will want to use the + * ccache versions of these APIs since they automatically store any + * newly created credentials. See \ref kim_ccache_overview for more + * information. + * + * + * \section kim_credential_acquire_new Acquiring New Credentials + * + * KIM provides the #kim_credential_create_new() API for acquiring new + * credentials. Credentials can either be obtained for a specific + * client identity or by specifying #KIM_IDENTITY_ANY to allow + * the user to choose. Typically callers of this API obtain the client + * identity using #kim_selection_hints_get_identity(). Depending on the + * kim_options specified, #kim_credential_create_new() may present a + * GUI or command line prompt to obtain information from the user. + * + * For legacy password-based Kerberos environments KIM also provides + * #kim_credential_create_new_with_password(). You should not use this + * function unless you know that it will only be used in environments using + * passwords. Otherwise users without passwords may be prompted for them. + * + * KIM provides the #kim_credential_create_from_keytab() to create credentials + * using a keytab. A keytab is an on-disk copy of a client identity's secret + * key. Typically sites use keytabs for client identities that identify a + * machine or service and protect the keytab with disk permissions. Because + * a keytab is sufficient to obtain credentials, keytabs will normally only + * be readable by root, Administrator or some other privileged account. + * Typically applications use credentials obtained from keytabs to obtain + * credentials for batch processes. These keytabs and credentials are usually + * for a special identity used for the batch process rather than a user + * identity. + * + * + * \section kim_credential_validate Validating Credentials + * + * A credential with a start time in the future (ie: after the issue date) + * is called a post-dated credential. Because the KDC administrator may + * wish to disable a identity, once the start time is reached, all post-dated + * credentials must be validated before they can be used. Otherwise an + * attacker using a compromised account could acquire lots of post-dated + * credentials to circumvent the acccount being disabled. + * + * KIM provides the #kim_credential_validate() API to validate a credential. + * Note that this API replaces the credential object with a new validated + * credential object. If you wish to store the new credential in the + * ccache collection you must either call #kim_credential_store() on the + * validated credential or use #kim_ccache_validate() instead. + * + * + * \section kim_credential_renew Renewing Credentials + * + * A renewable credential can be used to obtain a new identical credential + * without resending secret information (such as a password) to the KDC. + * A credential may only be renewed during its renewal lifetime and while + * valid. + * + * KIM provides the #kim_credential_renew() API to renew a credential. + * Note that this API replaces the credential object with a new renewed + * credential object. If you wish to store the new credential in the + * ccache collection you must either call #kim_credential_store() on the + * renewed credential or use #kim_ccache_renew() instead. + * + * + * \section kim_credential_storing Storing Credentials in the Cache Collection + * + * KIM credential objects may be stored in the ccache collection using + * #kim_credential_store(). This function runs any KIM authentication + * plugins on the credential and if the plugins return successfully, creates a + * new ccache for the credential's client identity in the cache collection + * and stores the credential in that ccache. Any existing ccaches and credentials + * for that client identity will be overwritten. #kim_credential_store() may + * optionally return a kim_ccache object for the new ccache if you need to perform + * further operations on the new ccache. + * + * Most of the time if you plan to store the credentials you are manipulating, you + * should use one of KIM ccache APIs. These functions perform the same operations + * except that they also call #kim_credential_store() any time the credential object + * changes. See \ref kim_ccache_overview for more information. + * + * + * \section kim_credential_iterator Iterating over the Credentials in a CCache + * + * KIM provides a simple iterator API for iterating over the credentials + * in a ccache. First, call #kim_credential_iterator_create() to obtain + * an iterator for a ccache. Then loop calling #kim_credential_iterator_next() + * until either you find the credential you are looking for or the API + * returns a NULL credential, indicating that there are no more + * credentials in the ccache. When you are done with the iterator, call + * #kim_credential_iterator_free(). + * + * \note #kim_credential_iterator_next() returns credential objects which + * must be freed with #kim_credential_free() to avoid leaking memory. + * + * + * \section kim_credential_verify Verifying Credentials + * + * When a program acquires TGT credentials for the purpose of authenticating + * itself to the machine it is running on, it is insufficient for the machine + * to assume that the caller is authorized just because it got credentials. + * Instead, the credentials must be verified using a key the local machine. + * The reason this is necessary is because an attacker can trick the + * machine into obtaining credentials from any KDC, including malicious ones + * with the same realm name as the local machine's realm. This exploit is + * called the Zanarotti attack. + * + * In order to avoid the Zanarotti attack, the local machine must authenticate + * the process in the same way an application server would authenticate a client. + * Like an application server, the local machine must have its own identity in + * its realm and a keytab for that identity on its local disk. However, + * rather than forcing system daemons to use the network-oriented calls in the + * krb5 and GSS APIs, KIM provides the #kim_credential_verify() API to + * verify credentials directly. + * + * The most common reason for using #kim_credential_verify() is user login. + * If the local machine wants to use Kerberos to verify the username and password + * provided by the user, it must call #kim_credential_verify() on the credentials + * it obtains to make sure they are really from a KDC it trusts. Another common + * case is a server which is only using Kerberos internally. For example an + * LDAP or web server might use a username and password obtained over the network + * to get Kerberos credentials. In order to make sure they aren't being tricked + * into talking to the wrong KDC, these servers must also call + * #kim_credential_verify(). + * + * The Zanarotti attack is only a concern if the act of accessing the machine + * gives the process special access. Thus a managed cluster machine with + * Kerberos-authenticated networked home directories does not need to call + * #kim_credential_verify(). Even though an attacker can log in as any user on + * the cluster machine, the attacker can't actually access any of the user's data + * or use any of their privileges because those are all authenticated via + * Kerberized application servers (and thus require actually having credentials + * for the real local realm). + * + * #kim_credential_verify() provides an option to + * return success even if the machine's host key is not present. This option + * exists for sites which have a mix of different machines, some of which are + * vulnerable to the Zanarotti attack and some are not. If this option is used, + * it is the responsiblity of the machine's maintainer to obtain a keytab + * for their machine if it needs one. + * + * + * \section kim_credential_properties Examining Credential Properties + * + * \li #kim_credential_get_client_identity() + * returns the credential's client identity. + * + * \li #kim_credential_get_service_identity() + * returns the credential's service identity. + * + * \li #kim_credential_is_tgt() + * returns whether the credential is a TGT (ie: "ticket-granting ticket"). TGTs are + * credentials for the krbtgt service: a service identity of the form "krbtgt/@". + * These credentials allow the entity named by the client identity to obtain + * additional service credentials without resending shared secrets (such as a password) + * to the KDC. Kerberos uses TGTs to provide single sign-on authentication. + * + * \li #kim_credential_get_state() + * returns a #kim_credential_state containing the state of the credential. + * Possible values are: + * * kim_credentials_state_valid + * * kim_credentials_state_expired + * * kim_credentials_state_not_yet_valid + * * kim_credentials_state_needs_validation + * * kim_credentials_state_address_mismatch + * + * \li #kim_credential_get_start_time() + * returns when the credential will become valid. + * Credentials may be "post-dated" which means that their lifetime starts sometime + * in the future. Note that when a post-dated credential's start time is reached, + * the credential must be validated. See \ref kim_credential_validate for more information. + * + * \li #kim_credential_get_expiration_time() + * returns when the credential will expire. + * Credentials are time limited by the lifetime of the credential. While you can + * request a credential of any lifetime, the KDC limits the credential lifetime + * to a administrator-defined maximum. Typically credential lifetime range from 10 + * to 21 hours. + * + * \li #kim_credential_get_renewal_expiration_time() + * returns when the credential will no longer be renewable. + * Valid credentials may be renewed up until their renewal expiration time. + * Renewing credentials acquires a fresh set of credentials with a full lifetime + * without resending secrets to the KDC (such as a password). If credentials are + * not renewable, this function will return a renewal expiration time of 0. + * + * \li #kim_credential_get_options() + * returns a kim_options object with the credential options of the + * credential. This function is intended to be used when adding + * an identity with existing credentials to the favorite identities list. + * By passing in the options returned by this call, future requests for the + * favorite identity will use the same credential options. + * + * + * See \ref kim_credential_reference and \ref kim_credential_iterator_reference for + * information on specific APIs. + */ + +/*! + * \defgroup kim_credential_iterator_reference KIM Credential Iterator Reference Documentation + * @{ + */ + +/*! + * \param out_credential_iterator on exit, a credential iterator object for \a in_ccache. + * Must be freed with kim_credential_iterator_free(). + * \param in_ccache a ccache object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a credential iterator to enumerate credentials in a ccache. + */ + +kim_error kim_credential_iterator_create (kim_credential_iterator *out_credential_iterator, + kim_ccache in_ccache); + +/*! + * \param in_credential_iterator a credential iterator object. + * \param out_credential on exit, the next credential in the ccache iterated by + * \a in_credential_iterator. Must be freed with + * kim_credential_free(). If there are no more credentials + * this argument will be set to NULL. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the next credential in a ccache. + */ + +kim_error kim_credential_iterator_next (kim_credential_iterator in_credential_iterator, + kim_credential *out_credential); + +/*! + * \param io_credential_iterator a credential iterator object to be freed. Set to NULL on exit. + * \brief Free memory associated with a credential iterator. + */ +void kim_credential_iterator_free (kim_credential_iterator *io_credential_iterator); + +/*!@}*/ + +/*! + * \defgroup kim_credential_reference KIM Credential Reference Documentation + * @{ + */ + +/*! + * \param out_credential on exit, a new credential object containing a newly acquired + * initial credential. Must be freed with kim_credential_free(). + * \param in_client_identity a client identity to obtain a credential for. Specify NULL to + * allow the user to choose the identity + * \param in_options options to control credential acquisition. + * \note #kim_credential_create_new() may + * present a GUI or command line prompt to obtain information from the user. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential. + * \sa kim_ccache_create_new + */ +kim_error kim_credential_create_new (kim_credential *out_credential, + kim_identity in_client_identity, + kim_options in_options); + +/*! + * \param out_credential on exit, a new credential object containing a newly acquired + * initial credential. Must be freed with kim_credential_free(). + * \param in_client_identity a client identity to obtain a credential for. Specify NULL to + * allow the user to choose the identity + * \param in_options options to control credential acquisition. + * \param in_password a password to be used while obtaining the credential. + * \note #kim_credential_create_new_with_password() exists to support + * legacy password-based Kerberos environments. You should not use this + * function unless you know that it will only be used in environments using passwords. + * This function may also present a GUI or command line prompt to obtain + * additional information needed to obtain credentials (eg: SecurID pin). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential using the provided password. + * \sa kim_ccache_create_new + */ +kim_error kim_credential_create_new_with_password (kim_credential *out_credential, + kim_identity in_client_identity, + kim_options in_options, + kim_string in_password); + +/*! + * \param out_credential on exit, a new credential object containing an initial credential + * for \a in_identity obtained using \a in_keytab. + * Must be freed with kim_credential_free(). + * \param in_identity a client identity to obtain a credential for. Specify NULL for + * the first identity in the keytab. + * \param in_options options to control credential acquisition. + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Acquire a new initial credential from a keytab. + * \sa kim_ccache_create_from_keytab + */ +kim_error kim_credential_create_from_keytab (kim_credential *out_credential, + kim_identity in_identity, + kim_options in_options, + kim_string in_keytab); + +/*! + * \param out_credential on exit, a new credential object which is a copy of \a in_krb5_creds. + * Must be freed with kim_credential_free(). + * \param in_krb5_context the krb5 context used to create \a in_krb5_creds. + * \param in_krb5_creds a krb5 credential object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a credential from a krb5 credential object. + */ +kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, + krb5_context in_krb5_context, + krb5_creds *in_krb5_creds); + +/*! + * \param out_credential on exit, a new credential object which is a copy of \a in_credential. + * Must be freed with kim_credential_free(). + * \param in_credential a credential object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a credential object. + */ +kim_error kim_credential_copy (kim_credential *out_credential, + kim_credential in_credential); + +/*! + * \param in_credential a credential object. + * \param in_krb5_context a krb5 context which will be used to create \a out_krb5_creds. + * \param out_krb5_creds on exit, a new krb5 creds object which is a copy of \a in_credential. + * Must be freed with krb5_free_creds(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a krb5 credentials object for a credential object. + */ +kim_error kim_credential_get_krb5_creds (kim_credential in_credential, + krb5_context in_krb5_context, + krb5_creds **out_krb5_creds); + +/*! + * \param in_credential a credential object. + * \param out_client_identity on exit, an identity object containing the client identity of + * \a in_credential. Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the client identity of a credential object. + */ +kim_error kim_credential_get_client_identity (kim_credential in_credential, + kim_identity *out_client_identity); + +/*! + * \param in_credential a credential object. + * \param out_service_identity on exit, an identity object containing the service identity of + * \a in_credential. Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the service identity of a credential object. + */ +kim_error kim_credential_get_service_identity (kim_credential in_credential, + kim_identity *out_service_identity); + +/*! + * \param in_credential a credential object. + * \param out_is_tgt on exit, whether or not the credential is a TGT. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Check if a credential is a ticket granting ticket. + */ +kim_error kim_credential_is_tgt (kim_credential in_credential, + kim_boolean *out_is_tgt); + +/*! + * \param in_credential a credential object. + * \param out_state on exit, the state of the credential. See #kim_credential_state_enum + * for the possible values of \a out_state. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Check the state of a credential (valid, expired, postdated, etc). + */ +kim_error kim_credential_get_state (kim_credential in_credential, + kim_credential_state *out_state); + +/*! + * \param in_credential a credential object. + * \param out_start_time on exit, the time when \a in_credential becomes valid. + * May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials become valid. + * \sa kim_ccache_get_start_time + */ +kim_error kim_credential_get_start_time (kim_credential in_credential, + kim_time *out_start_time); + +/*! + * \param in_credential a credential object. + * \param out_expiration_time on exit, the time when \a in_credential will expire. + * May be in the past or future. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials will expire. + * \sa kim_ccache_get_expiration_time + */ +kim_error kim_credential_get_expiration_time (kim_credential in_credential, + kim_time *out_expiration_time); + +/*! + * \param in_credential a credential object. + * \param out_renewal_expiration_time on exit, the time when \a in_credential will no longer + * be renewable. May be in the past or future. If + * credentials are not renewable at all, returns 0. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the time when the credentials will no longer be renewable. + * \sa kim_ccache_get_renewal_expiration_time + */ +kim_error kim_credential_get_renewal_expiration_time (kim_credential in_credential, + kim_time *out_renewal_expiration_time); + +/*! + * \param in_credential a credential object. + * \param out_options on exit, an options object reflecting the ticket + * options of \a in_credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a kim_options object based on a credential's attributes. + */ +kim_error kim_credential_get_options (kim_credential in_credential, + kim_options *out_options); + +/*! + * \param in_credential a credential object. + * \param in_client_identity a client identity. + * \param out_ccache on exit, a ccache object containing \a in_credential with the client + * identity \a in_client_identity. Must be freed with kim_ccache_free(). + * Specify NULL if you don't want this return value. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Store a credential in a ccache in the cache collection. + */ +kim_error kim_credential_store (kim_credential in_credential, + kim_identity in_client_identity, + kim_ccache *out_ccache); + +/*! + * \param in_credential a TGT credential to be verified. + * \param in_service_identity a service identity to look for in the keytab. Specify + * KIM_IDENTITY_ANY to use the default service identity + * (usually host/@). + * \param in_keytab a path to a keytab. Specify NULL for the default keytab location. + * \param in_fail_if_no_service_key whether or not the absence of a key for \a in_service_identity + * in the host's keytab will cause a failure. + * \note specifying FALSE for \a in_fail_if_no_service_key may expose the calling program to + * the Zanarotti attack if the host has no keytab installed. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Verify a TGT credential. + * \sa kim_ccache_verify + */ +kim_error kim_credential_verify (kim_credential in_credential, + kim_identity in_service_identity, + kim_string in_keytab, + kim_boolean in_fail_if_no_service_key); + +/*! + * \param io_credential a TGT credential to be renewed. On exit, the old credential + * object will be freed and \a io_credential will be replaced + * with a new renewed credential. The new credential must be freed + * with kim_credential_free(). + * \param in_options initial credential options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Renew a TGT credential. + * \sa kim_ccache_renew + */ +kim_error kim_credential_renew (kim_credential *io_credential, + kim_options in_options); + +/*! + * \param io_credential a credential object to be validated. On exit, the old credential + * object will be freed and \a io_credential will be replaced + * with a new validated credential. The new credential must be freed + * with kim_credential_free(). + * \param in_options initial credential options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Validate a TGT credential. + * \sa kim_ccache_validate + */ +kim_error kim_credential_validate (kim_credential *io_credential, + kim_options in_options); + +/*! + * \param io_credential the credential object to be freed. Set to NULL on exit. + * \brief Free memory associated with a credential object. + */ +void kim_credential_free (kim_credential *io_credential); + +/*!@}*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_CREDENTIAL_H */ diff --git a/krb5-1-7/src/include/kim/kim_identity.h b/krb5-1-7/src/include/kim/kim_identity.h new file mode 100644 index 000000000..cd50a4080 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_identity.h @@ -0,0 +1,286 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_IDENTITY_H +#define KIM_IDENTITY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/*! + * \ingroup kim_types_reference + * Constant to specify any Kerberos identity is acceptable. + */ +#define KIM_IDENTITY_ANY ((kim_identity) NULL) + +/*! + * \page kim_identity_overview KIM Identity Overview + * + * \section kim_identity_introduction Introduction + * + * Identities in Kerberos are named by "principals". These identies may be people (users) + * or services (a server running on a host). When Kerberos issues credentials which + * authenticate one identity to another, the identity being authenticated is called + * the "client identity" and the identity being authenticated to is called the + * "service identity". + * + * Kerberos identities are made up of one or more components, as well as the Kerberos realm + * the entity belongs to. For client identities the first component is usually the client + * username (eg: "jdoe"). For service identities the first component is the name of the + * service (eg: "imap"). + * + * Kerberos identities have both a binary (opaque) representation and also a string + * representation. The string representation consists of the components separated by '/' + * followed by an '@' and then the realm. For example, the identity "jdoe/admin@EXAMPLE.COM" + * represents John Doe's administrator identity at the realm EXAMPLE.COM. Note that + * identity components may contain both '/' and '@' characters. When building a + * identity from its string representation these syntactic characters must be escaped + * with '\'. + * + * + * \section kim_identity_create_display Creating and Displaying Identities + * + * KIM Identities can be generated from components, their escaped string representation + * or from a krb5_principal. Once you have a KIM identity object, you can also get + * the component, string or krb5_principal representations back out: + * + * \li #kim_identity_create_from_components() creates an identity object from a list of components. + * \li #kim_identity_get_number_of_components() returns the number of components in an identity object. + * \li #kim_identity_get_component_at_index() return a component of an identity object. + * \li #kim_identity_get_realm() returns the identity's realm. + * + * \li #kim_identity_create_from_string() generates an identity object from an escaped string representation. + * \li #kim_identity_get_string() returns the identity's escaped string representation. + * \li #kim_identity_get_display_string() returns a non-escaped string for display to the user. + * This string cannot be passed into #kim_identity_create_from_string(). + * + * \li #kim_identity_create_from_krb5_principal() generates an identity object from a krb5_principal object. + * \li #kim_identity_get_krb5_principal() returns a krb5_principal object for an identity object. + * + * \note If you need to know if two identity objects refer to the same entity, use #kim_identity_compare(). + * + * + * \section kim_identity_selection Choosing a Client Identity + * + * Unfortunately most of the time applications don't know what client identity to use. + * Users may have identities for multiple Kerberos realms, as well as multiple identities + * in a single realm (such as a user and administrator identity). + * + * To solve this problem, #kim_selection_hints_get_identity() takes information + * from the application in the form of a selection hints object and returns the best + * matching client identity, if one is available. See \ref kim_selection_hints_overview + * for more information. + * + * + * \section kim_identity_password Changing a Identity's Password + * + * Many Kerberos sites use passwords for user accounts. Because passwords may be + * stolen or compromised, they must be frequently changed. KIM provides APIs to + * change the identity's password directly, and also handles changing the identity's + * password when it has expired. + * + * #kim_identity_change_password() presents a user interface to obtain the old and + * new passwords from the user. + * + * \note Not all identities have a password. Some sites use certificates (pkinit) + * and in the future there may be other authentication mechanisms (eg: smart cards). + * + * See \ref kim_identity_reference for information on specific APIs. + */ + +/*! + * \defgroup kim_identity_reference KIM Identity Reference Documentation + * @{ + */ + +/*! + * \param out_identity on exit, a new identity object. Must be freed with kim_identity_free(). + * \param in_string a string representation of a Kerberos identity. + * Special characters such as '/' and '@' must be escaped with '\'. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create a identity from a string. + */ +kim_error kim_identity_create_from_string (kim_identity *out_identity, + kim_string in_string); + +/*! + * \param out_identity on exit, a new identity object. Must be freed with kim_identity_free(). + * \param in_realm a string representation of a Kerberos realm. + * \param in_1st_component a string representing the first component of the identity. + * \param ... zero or more strings of type kim_string_t representing additional components + * of the identity followed by a terminating NULL. Components will be assembled in + * order (ie: the 4th argument to kim_identity_create_from_components() will be + * the 2nd component of the identity). + * \note The last argument must be a NULL or kim_identity_create_from_components() may crash. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create a identity from a realm and component strings. + */ +kim_error kim_identity_create_from_components (kim_identity *out_identity, + kim_string in_realm, + kim_string in_1st_component, + ...); + +/*! + * \param out_identity on exit, a new identity object which is a copy of \a in_krb5_principal. + * Must be freed with kim_identity_free(). + * \param in_krb5_context the krb5 context used to create \a in_krb5_principal. + * \param in_krb5_principal a krb5 principal object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create an identity object from a krb5_principal. + */ +kim_error kim_identity_create_from_krb5_principal (kim_identity *out_identity, + krb5_context in_krb5_context, + krb5_principal in_krb5_principal); + +/*! + * \param out_identity on exit, a new identity object which is a copy of \a in_identity. + * Must be freed with kim_identity_free(). + * \param in_identity an identity object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy an identity object. + */ +kim_error kim_identity_copy (kim_identity *out_identity, + kim_identity in_identity); + + +/*! + * \param in_identity an identity object. + * \param in_compare_to_identity an identity object. + * \param out_comparison on exit, a comparison of \a in_identity and + * \a in_compare_to_identity which determines whether + * or not the two identities are equivalent and their + * sort order (for display to the user) if they are not. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Compare identity objects for equivalency. + */ +kim_error kim_identity_compare (kim_identity in_identity, + kim_identity in_compare_to_identity, + kim_comparison *out_comparison); +/*! + * \param in_identity an identity object. + * \param out_string on exit, a string representation of \a in_identity. + * Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the string representation of a identity. + * \note Special characters such as '@' and '/' will be escaped with '\'. + */ +kim_error kim_identity_get_string (kim_identity in_identity, + kim_string *out_string); + + +/*! + * \param in_identity an identity object. + * \param out_display_string on exit, a string representation of \a in_identity appropriate for + * display to the user. Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a human-readable string representation of an identity. + * \note Special characters such as '/' and '@' are \em not escaped with '\'. As a result the + * string returned from this function cannot be used with kim_identity_create_from_string() + * because it does not uniquely specify a principal. + * The result of this function should \em only be used to display to the user. + */ +kim_error kim_identity_get_display_string (kim_identity in_identity, + kim_string *out_display_string); + +/*! + * \param in_identity an identity object. + * \param out_realm_string on exit, a string representation of \a in_identity's realm. + * Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the realm string of an identity. + */ +kim_error kim_identity_get_realm (kim_identity in_identity, + kim_string *out_realm_string); + +/*! + * \param in_identity an identity object. + * \param out_number_of_components on exit the number of components in \a in_identity. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the number of components of an identity. + */ +kim_error kim_identity_get_number_of_components (kim_identity in_identity, + kim_count *out_number_of_components); + +/*! + * \param in_identity an identity object. + * \param in_index the index of the desired component. Component indexes start at 0. + * \param out_component_string on exit, a string representation of the component in \a in_identity + * specified by \a in_index. Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the Nth component of an identity. + */ +kim_error kim_identity_get_component_at_index (kim_identity in_identity, + kim_count in_index, + kim_string *out_component_string); + +/*! + * \param in_identity an identity object. + * \param out_components on exit, a string of the non-realm components of \a in_identity + * separated by '/' characters. Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a display string of the non-realm components of an identity. + */ +kim_error kim_identity_get_components_string (kim_identity in_identity, + kim_string *out_components); + +/*! + * \param in_identity an identity object. + * \param in_krb5_context a krb5 context object. + * \param out_krb5_principal on exit, a krb5_principal representation of \a in_identity + * allocated with \a in_krb5_context. Must be freed with + * krb5_free_principal() using \a in_krb5_context. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the krb5_principal representation of an identity. + */ +kim_error kim_identity_get_krb5_principal (kim_identity in_identity, + krb5_context in_krb5_context, + krb5_principal *out_krb5_principal); + +/*! + * \param in_identity an identity object whose password will be changed. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Change the password for an identity. + * \note kim_identity_change_password() will acquire a temporary credential to change + * the password. + */ +kim_error kim_identity_change_password (kim_identity in_identity); + +/*! + * \param io_identity the identity object to be freed. Set to NULL on exit. + * \brief Free memory associated with an identity. + */ +void kim_identity_free (kim_identity *io_identity); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_IDENTITY_H */ diff --git a/krb5-1-7/src/include/kim/kim_library.h b/krb5-1-7/src/include/kim/kim_library.h new file mode 100644 index 000000000..681f58e79 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_library.h @@ -0,0 +1,83 @@ +/* + * Copyright 2005-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_LIBRARY_H +#define KIM_LIBRARY_H + +#include + +/*! + * \defgroup kim_library_reference KIM Library Documentation + * @{ + */ + +/*! Do not present user interface */ +#define KIM_UI_ENVIRONMENT_NONE 0 +/*! Automatically determine what user interface is appropriate (default). */ +#define KIM_UI_ENVIRONMENT_AUTO 1 +/*! Present a graphical user interface */ +#define KIM_UI_ENVIRONMENT_GUI 2 +/*! Present a command line user interface */ +#define KIM_UI_ENVIRONMENT_CLI 3 + +/*! An integer describing the type of user interface to use. */ +typedef int kim_ui_environment; + +/*! + * \param in_ui_environment an integer value describing the type of user interface to use. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note Set to KIM_UI_ENVIRONMENT_AUTO by default. + * \brief Tell KIM how to present UI from your application. + */ +kim_error kim_library_set_ui_environment (kim_ui_environment in_ui_environment); + +/*! + * \param in_allow_access a boolean containing whether or not to touch the user's home directory. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This API is usually used for Kerberos authenticated home directories to prevent a deadlock. + * \brief Tells KIM whether or not it is allowed to touch the user's home directory. + */ +kim_error kim_library_set_allow_home_directory_access (kim_boolean in_allow_access); + +/*! + * \param in_allow_automatic_prompting a boolean containing whether or not to prompt automatically. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Tells KIM whether or not it is allowed to automatically present user interface. + */ +kim_error kim_library_set_allow_automatic_prompting (kim_boolean in_allow_automatic_prompting); + +/*! + * \param in_application_name a string containing the localized name of your application. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note On many operating systems KIM can determine the caller's application + * name automatically. This call exists for applications to use when those + * mechanisms fail or do not exist. + * \brief Set the name of your application for KIM to use for user interface. + */ +kim_error kim_library_set_application_name (kim_string in_application_name); + +/*!@}*/ + +#endif /* KIM_LIBRARY_H */ diff --git a/krb5-1-7/src/include/kim/kim_options.h b/krb5-1-7/src/include/kim/kim_options.h new file mode 100644 index 000000000..d36aa0c02 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_options.h @@ -0,0 +1,431 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_OPTIONS_H +#define KIM_OPTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + * \addtogroup kim_types_reference + * @{ + */ + +/*! + * Specifies the user's default options. + */ +#define KIM_OPTIONS_DEFAULT ((kim_options) NULL) + +/*! + * Specifies that credentials should be valid immediately. + */ +#define KIM_OPTIONS_START_IMMEDIATELY ((kim_time_t) 0) + +/*! @} */ + +/*! + * \page kim_options_overview KIM Options Overview + * + * \section kim_options_introduction Introduction + * + * Kerberos Identity Management Options (kim_options_t) allows you to control how + * the Kerberos library obtains credentials. When the options structure is initialized with + * #kim_options_create(), each option is filled in with a default value which can then be modified + * with the kim_options_set_*() APIs. If you only want to use the default values, you may pass + * #KIM_OPTIONS_DEFAULT into any KIM function that takes a kim_options_t. + * + * KIM options fall into two major categories: options for controlling how credentials are + * acquired and options for controlling what properties the newly acquired credentials will have: + * + * \section kim_options_credential_properties Options for Controlling Credential Properties + * + * Kerberos credentials have a number of different properties which can be requested + * when credentials are acquired. These properties control when and for how long the + * credentials are valid and what you can do with them. + + * Note that setting these properties in the KIM options only changes what the Kerberos + * libraries \em request from the KDC. The KDC itself may choose not to honor your + * requested properties if they violate the site security policy. For example, most sites + * place an upper bound on how long credentials may be valid. If you request a credential + * lifetime longer than this upper bound, the KDC may return credentials with a shorter + * lifetime than you requested. + * + * \subsection kim_options_lifetimes Credential Lifetime + * + * Kerberos credentials have start time and a lifetime during which they are valid. + * Once the lifetime has passed, credentials "expire" and can no longer be used. + * + * The requested credential start time can be set with #kim_options_set_start_time() + * and examined with #kim_options_get_start_time(). The requested credential + * lifetime can be set with #kim_options_set_lifetime() and examined with + * #kim_options_get_lifetime(). + * + * \subsection kim_options_renewable Renewable Credentials + * + * Credentials with very long lifetimes are more convenient since the user does not + * have authenticate as often. Unfortunately they are also a higher security + * risk: if credentials are stolen they can be used until they expire. + * Credential renewal exists to compromise between these two conflicting goals. + * + * Renewable credentials are TGT credentials which can be used to obtain new + * TGT credentials without reauthenticating. By regularly renewing credentials + * the KDC has an opportunity to check to see if the client's credentials have been + * reported stolen and refuse to renew them. Renewable credentials have a "renewal + * lifetime" during which credentials can be renewed. This lifetime is relative + * to the original credential start time. If credentials are renewed shortly before + * the end of the renewal lifetime, their lifetime will be capped to the end of the + * renewal lifetime. + * + * Note that credentials must be valid to be renewed and therefore may not be + * an appropriate solution for all use cases. Sites which use renewable + * credentials often create helper processes running as the user which will + * automatically renew the user's credentials when they get close to expiration. + * + * Use #kim_options_set_renewable() to change whether or not the Kerberos libraries + * request renewable credentials and #kim_options_get_renewable() to find out the + * current setting. Use #kim_options_set_renewal_lifetime() to change the requested + * renewal lifetime and #kim_options_get_renewal_lifetime() to find out the current + * value. + * + * \subsection kim_options_addressless Addressless Credentials + * + * Traditionally Kerberos used the host's IP address as a mechanism to restrict + * the user's credentials to a specific host, thus making it harder to use stolen + * credentials. When authenticating to a remote service with credentials containing + * addresses, the remote service verifies that the client's IP address is one of the + * addresses listed in the credential. Unfortunately, modern network technologies + * such as NAT rewrite the IP address in transit, making it difficult to use + * credentials with addresses in them. As a result, most Kerberos sites now obtain + * addressless credentials. + * + * Use #kim_options_set_addressless() to change whether or not the Kerberos libraries + * request addressless credentials. Use #kim_options_get_addressless() to find out the + * current setting. + * + * \subsection kim_options_forwardable Forwardable Credentials + * + * Forwardable credentials are TGT credentials which can be forwarded to a service + * you have authenticated to. If the credentials contain IP addresses, the addresses + * are changed to reflect the service's IP address. Credential forwarding is most + * commonly used for Kerberos-authenticated remote login services. By forwarding + * TGT credentials through the remote login service, the user's credentials will + * appear on the remote host when the user logs in. + * + * The forwardable flag only applies to TGT credentials. + * + * Use #kim_options_set_forwardable() to change whether or not the Kerberos libraries + * request forwardable credentials. Use #kim_options_get_forwardable() to find out the + * current setting. + * + * \subsection kim_options_proxiable Proxiable Credentials + * + * Proxiable credentials are similar to forwardable credentials except that instead of + * forwarding the a TGT credential itself, a service credential is forwarded + * instead. Using proxiable credentials, a user can permit a service to perform + * a specific task as the user using one of the user's service credentials. + * + * Like forwardability, the proxiable flag only applies to TGT credentials. Unlike + * forwarded credentials, the IP address of proxiable credentials are not modified for + * the service when being proxied. This can be solved by also requesting addressless + * credentials. + * + * Use #kim_options_set_proxiable() to change whether or not the Kerberos libraries + * request proxiable credentials. Use #kim_options_get_proxiable() to find out the + * current setting. + * + * \subsection kim_options_service_name Service Name + * + * Normally users acquire TGT credentials (ie "ticket granting tickets") and then + * use those credentials to acquire service credentials. This allows Kerberos to + * provide single sign-on while still providing mutual authentication to services. + * However, sometimes you just want an initial credential for a service. KIM + * options allows you to set the service name with + * #kim_options_set_service_name() and query it with + * #kim_options_get_service_name(). + * + * See \ref kim_options_reference for information on specific APIs. + */ + +/*! + * \defgroup kim_options_reference KIM Options Reference Documentation + * @{ + */ + +/*! + * \param out_options on exit, a new options object. Must be freed with kim_options_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create new options with default values. + */ +kim_error kim_options_create (kim_options *out_options); + +/*! + * \param out_options on exit, a new options object which is a copy of \a in_options. + * Must be freed with kim_options_free(). If passed KIM_OPTIONS_DEFAULT + * will set \a out_options to KIM_OPTIONS_DEFAULT. + * \param in_options a options object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy options. + */ +kim_error kim_options_copy (kim_options *out_options, + kim_options in_options); + +/*! + * \param io_options an options object to modify. + * \param in_start_time a start date (in seconds since January 1, 1970). Set to + * #KIM_OPTIONS_START_IMMEDIATELY for the acquired credential to be valid + * immediately. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the date when a credential should become valid. + * \note When using a start time in the future, once the start time has been reached the credential + * must be validated before it can be used. + * \par Default value + * 0, indicating "now". The credential will be valid immediately. + * \sa kim_options_get_start_time(), kim_credential_validate(), kim_ccache_validate(), kim_identity_validate() + */ +kim_error kim_options_set_start_time (kim_options io_options, + kim_time in_start_time); + +/*! + * \param in_options an options object. + * \param out_start_time on exit, the start date (in seconds since January 1, 1970) specified by + * \a in_options. #KIM_OPTIONS_START_IMMEDIATELY indicates the credential + * will be valid immediately. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the date when a credential should become valid. + * \note When using a start time in the future, once the start time has been reached the credential + * must be validated before it can be used. + * \par Default value + * 0, indicating "now". The credential will be valid immediately. + * \sa kim_options_set_start_time(), kim_credential_validate(), kim_ccache_validate(), kim_identity_validate() + */ +kim_error kim_options_get_start_time (kim_options in_options, + kim_time *out_start_time); + +/*! + * \param io_options an options object to modify. + * \param in_lifetime a lifetime duration (in seconds). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the duration during which a credential should be valid. + * \note KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). + * As a result the credential will actually have a lifetime which is the minimum of + * \a in_lifetime and the KDC's maximum allowed lifetime. + * \sa kim_options_get_lifetime() + * \par Default value + * Read from the user's preferences and the Kerberos configuration. 10 hours if unspecified. + */ +kim_error kim_options_set_lifetime (kim_options io_options, + kim_lifetime in_lifetime); + +/*! + * \param in_options an options object. + * \param out_lifetime on exit, the lifetime duration (in seconds) specified in \a in_options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the duration during which an acquired credential should be valid. + * \note KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). + * As a result the credential will actually have a lifetime which is the minimum of + * \a in_lifetime and the KDC's maximum allowed lifetime. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. 10 hours if unspecified. + * \sa kim_options_set_lifetime() + */ +kim_error kim_options_get_lifetime (kim_options in_options, + kim_lifetime *out_lifetime); + +/*! + * \param io_options an options object to modify. + * \param in_renewable a boolean value indicating whether or not to request a renewable + * credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to request a renewable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_get_renewable() + */ +kim_error kim_options_set_renewable (kim_options io_options, + kim_boolean in_renewable); + +/*! + * \param in_options an options object. + * \param out_renewable on exit, a boolean value indicating whether or \a in_options will + * request a renewable credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to request a renewable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_set_renewable() + */ +kim_error kim_options_get_renewable (kim_options in_options, + kim_boolean *out_renewable); + +/*! + * \param io_options an options object to modify. + * \param in_renewal_lifetime a renewal lifetime duration (in seconds). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the duration during which a valid credential should be renewable. + * \note KDCs have a maximum allowed renewal lifetime per identity (usually 10 to 21 hours). + * As a result the credential will actually have a lifetime which is the minimum of + * \a in_lifetime and the KDC's maximum allowed lifetime. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. 7 days if unspecified. + * \sa kim_options_get_renewal_lifetime(), kim_identity_renew(), kim_credential_renew(), kim_ccache_renew() + */ +kim_error kim_options_set_renewal_lifetime (kim_options io_options, + kim_lifetime in_renewal_lifetime); + +/*! + * \param in_options an options object. + * \param out_renewal_lifetime on exit, the renewal lifetime duration (in seconds) specified + * in \a in_options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the duration during which a valid credential should be renewable. + * \note KDCs have a maximum allowed lifetime per identity (usually 10 to 21 hours). + * As a result the credential will actually have a lifetime which is the minimum of + * \a in_lifetime and the KDC's maximum allowed lifetime. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. 7 days if unspecified. + * \sa kim_options_set_renewal_lifetime(), kim_identity_renew(), kim_credential_renew(), kim_ccache_renew() + */ +kim_error kim_options_get_renewal_lifetime (kim_options in_options, + kim_lifetime *out_renewal_lifetime); + +/*! + * \param io_options an options object to modify. + * \param in_forwardable a boolean value indicating whether or not to request a forwardable + * credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to request a forwardable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_get_forwardable() + */ +kim_error kim_options_set_forwardable (kim_options io_options, + kim_boolean in_forwardable); + +/*! + * \param in_options an options object. + * \param out_forwardable on exit, a boolean value indicating whether or \a in_options will + * request a forwardable credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to request a forwardable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_set_forwardable() + */ +kim_error kim_options_get_forwardable (kim_options in_options, + kim_boolean *out_forwardable); + +/*! + * \param io_options an options object to modify. + * \param in_proxiable a boolean value indicating whether or not to request a proxiable + * credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to request a proxiable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_get_proxiable() + */ +kim_error kim_options_set_proxiable (kim_options io_options, + kim_boolean in_proxiable); + +/*! + * \param in_options an options object. + * \param out_proxiable on exit, a boolean value indicating whether or \a in_options will + * request a proxiable credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to request a proxiable credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_set_proxiable() + */ +kim_error kim_options_get_proxiable (kim_options in_options, + kim_boolean *out_proxiable); + +/*! + * \param io_options an options object to modify. + * \param in_addressless a boolean value indicating whether or not to request an addressless + * credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to request an addressless credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_get_addressless() + */ +kim_error kim_options_set_addressless (kim_options io_options, + kim_boolean in_addressless); + +/*! + * \param in_options an options object. + * \param out_addressless on exit, a boolean value indicating whether or \a in_options will + * request an addressless credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to request an addressless credential. + * \par Default value + * Read from the user's preferences and the Kerberos configuration. TRUE if unspecified. + * \sa kim_options_set_addressless() + */ +kim_error kim_options_get_addressless (kim_options in_options, + kim_boolean *out_addressless); + +/*! + * \param io_options an options object to modify. + * \param in_service_name a service name. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the service name to request a credential for. + * \par Default value + * NULL, indicating "krbtgt@", the ticket granting ticket (TGT) service. + * \sa kim_options_get_service_name() + */ +kim_error kim_options_set_service_name (kim_options io_options, + kim_string in_service_name); + +/*! + * \param in_options an options object. + * \param out_service_name on exit, the service name specified in \a in_options. + * Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the service name to request a credential for. + * \par Default value + * NULL, indicating "krbtgt@", the ticket granting ticket (TGT) service. + * \sa kim_options_set_service_name() + */ +kim_error kim_options_get_service_name (kim_options in_options, + kim_string *out_service_name); + +/*! + * \param io_options the options object to be freed. Set to NULL on exit. + * \brief Free memory associated with an options object. + */ +void kim_options_free (kim_options *io_options); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_OPTIONS_H */ diff --git a/krb5-1-7/src/include/kim/kim_preferences.h b/krb5-1-7/src/include/kim/kim_preferences.h new file mode 100644 index 000000000..d7970ba04 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_preferences.h @@ -0,0 +1,419 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_PREFERENCES_H +#define KIM_PREFERENCES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + * \page kim_preferences_overview KIM Preferences Overview + * + * \section kim_preferences_introduction Introduction + * + * In addition to the site preferences stored in the Kerberos configuration, users may also + * want to have their own personal preferences for controlling credential acquisition. + * As a result, KIM provides user preferences for initial credential options and + * user interface behavior such as the default client identity and the favorite identities list. + * + * \section kim_preferences_edit Viewing and Editing the Preferences + * + * In order to view and edit the user's preferences, call #kim_preferences_create() to acquire a + * preferences object containing the user's preferences. You can examine preferences + * with the functions starting with "kim_preferences_get_" and change preferences with + * the functions starting with "kim_preferences_set_". Once you are done making changes, + * you can write changes back out to the user's preferences with #kim_preferences_synchronize(). + * + * \note The location of user preferences and the semantics of + * preference synchronization is platform-specific. Where possible KIM will use + * platform-specific preference mechanisms. + * + * \section kim_preferences_options Initial Credential Options Preferences + * + * KIM provides user preferences for initial credential options. These + * are the options #kim_options_create() will use when creating a new KIM + * options object. They are also the options specified by KIM_OPTIONS_DEFAULT. + * You can view and edit the initial credential options using + * #kim_preferences_get_options() and #kim_preferences_set_options(). + * + * \note Not all credential options in the kim_options_t object have corresponding + * user preferences. For example, the prompt callback function is not stored + * in the user preferences since it has no meaning outside of the current + * application. Some options which are not currently stored in the + * preferences may be stored there in the future. + * + * If you are implementing a user interface for credentials acquisition, + * you should be aware that KIM has a user preference to manage the initial + * credential options preferences. If the user successfully acquires credentials + * with non-default options and #kim_preferences_get_remember_options() is set + * to TRUE, you should store the options used to get credentials with + * #kim_preferences_set_options(). + * + * \section kim_preferences_client_identity Client Identity Preferences + * + * KIM also provides user preferences for the default client identity. + * This identity is used whenever KIM needs to display a graphical dialog for + * credential acquisition but does not know what client identity to use. + * You can view and edit the default client identity using + * #kim_preferences_get_client_identity() and + * #kim_preferences_set_client_identity(). + * + * If you are implementing a user interface for credentials acquisition, + * you should be aware that KIM has a user preference to manage + * the client identity preferences. If the user successfully acquires credentials + * with non-default options and #kim_preferences_get_remember_client_identity() is + * set to TRUE, you should store the client identity for which credentials were + * acquired using #kim_preferences_set_client_identity(). + * + * \section kim_preferences_favorite_identities Favorite Identities Preferences + * + * As Kerberos becomes more widespread, the number of possible Kerberos + * identities and realms a user might want to use will become very large. + * Sites may list hundreds of realms in their Kerberos configuration files. + * In addition, sites may wish to use DNS SRV records to avoid having to list + * all the realms they use in their Kerberos configuration. As a result, the + * list of realms in the Kerberos configuration may be exceedingly large and/or + * incomplete. Users may also use multiple identities from the same realm. + * + * On platforms which use a GUI to acquire credentials, the KIM would like + * to to display a list of identities for the user to select from. Depending on + * what is appropriate for the platform, identities may be displayed in a popup + * menu or other list. + * + * To solve this problem, the KIM maintains a list of favorite identities + * specifically for identity selection. This list is a set of unique identities + * in alphabetical order (as appropriate for the user's language localization). + * + * Each identity may optionally have its own options for ticket acquisition. + * This allows KIM UIs to remember what ticket options worked for a specific + * identity. For example if the user normally wants renewable tickets but + * they have one identity at a KDC which rejects requests for renewable tickets, + * the "not renewable" option can be associated with that identity without + * changing the user's default preference to get renewable tickets. If an + * identity should use the default options, just pass KIM_OPTIONS_DEFAULT. + * + * Most callers will not need to use the favorite identities APIs. However if you + * are implementing your own graphical prompt callback or a credential management + * application, you may to view and/or edit the user's favorite identities. + * + * \section kim_favorite_identities_edit Viewing and Editing the Favorite Identities + * + * First, you need to acquire the Favorite Identities stored in the user's + * preferences using #kim_preferences_create(). + * + * Then use #kim_preferences_get_number_of_favorite_identities() and + * #kim_preferences_get_favorite_identity_at_index() to display the identities list. + * Use #kim_preferences_add_favorite_identity() and #kim_preferences_remove_favorite_identity() + * to change which identities are in the identities list. Identities are always stored in + * alphabetical order and duplicate identities are not permitted, so when you add or remove a + * identity you should redisplay the entire list. If you wish to replace the + * identities list entirely, use #kim_preferences_remove_all_favorite_identities() + * to clear the list before adding your identities. + * + * Once you are done editing the favorite identities list, store changes in the + * user's preference file using #kim_preferences_synchronize(). + * + * See \ref kim_preferences_reference for information on specific APIs. + */ + +/*! + * \defgroup kim_preferences_reference KIM Preferences Documentation + * @{ + */ + +/*! + * \param out_preferences on exit, a new preferences object. + * Must be freed with kim_preferences_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create a new preferences object from the current user's preferences. + */ +kim_error kim_preferences_create (kim_preferences *out_preferences); + +/*! + * \param out_preferences on exit, a new preferences object which is a copy of in_preferences. + * Must be freed with kim_preferences_free(). + * \param in_preferences a preferences object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a preferences object. + */ +kim_error kim_preferences_copy (kim_preferences *out_preferences, + kim_preferences in_preferences); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_options an options object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the user's preferred options. + * \sa kim_preferences_get_options() + */ +kim_error kim_preferences_set_options (kim_preferences io_preferences, + kim_options in_options); + +/*! + * \param in_preferences a preferences object. + * \param out_options on exit, the options specified in \a in_preferences. + * May be KIM_OPTIONS_DEFAULT. + * If not, must be freed with kim_options_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the user's preferred options. + * \sa kim_preferences_set_options() + */ +kim_error kim_preferences_get_options (kim_preferences in_preferences, + kim_options *out_options); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_remember_options a boolean value indicating whether or not to remember the last + * options used to acquire a credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to remember the last options the user used to acquire a credential. + * \sa kim_preferences_get_remember_options() + */ +kim_error kim_preferences_set_remember_options (kim_preferences io_preferences, + kim_boolean in_remember_options); + +/*! + * \param in_preferences a preferences object. + * \param out_remember_options on exit, a boolean value indicating whether or \a in_preferences will + * remember the last options used to acquire a credential. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to remember the last options the user used to acquire a credential. + * \sa kim_preferences_set_remember_options() + */ +kim_error kim_preferences_get_remember_options (kim_preferences in_preferences, + kim_boolean *out_remember_options); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_client_identity a client identity object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the user's preferred client identity. + * \sa kim_preferences_get_client_identity() + */ +kim_error kim_preferences_set_client_identity (kim_preferences io_preferences, + kim_identity in_client_identity); + +/*! + * \param in_preferences a preferences object. + * \param out_client_identity on exit, the client identity specified in \a in_preferences. + * Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the user's preferred client identity. + * \sa kim_preferences_set_client_identity() + */ +kim_error kim_preferences_get_client_identity (kim_preferences in_preferences, + kim_identity *out_client_identity); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_remember_client_identity a boolean value indicating whether or not to remember the last + * client identity for which a credential was acquired. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set whether or not to remember the last client identity the user acquired a credential for. + * \sa kim_preferences_get_remember_client_identity() + */ +kim_error kim_preferences_set_remember_client_identity (kim_preferences io_preferences, + kim_boolean in_remember_client_identity); + +/*! + * \param in_preferences a preferences object. + * \param out_remember_client_identity on exit, a boolean value indicating whether or \a in_preferences will + * remember the last client identity for which a credential was acquired. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get whether or not to remember the last client identity the user acquired a credential for. + * \sa kim_preferences_set_remember_client_identity() + */ +kim_error kim_preferences_get_remember_client_identity (kim_preferences in_preferences, + kim_boolean *out_remember_client_identity); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_minimum_lifetime a minimum lifetime indicating how small a lifetime the + * GUI tools should allow the user to specify for credentials. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the minimum credential lifetime for GUI credential lifetime controls. + * \sa kim_preferences_get_minimum_lifetime() + */ +kim_error kim_preferences_set_minimum_lifetime (kim_preferences io_preferences, + kim_lifetime in_minimum_lifetime); + +/*! + * \param in_preferences a preferences object. + * \param out_minimum_lifetime on exit, the minimum lifetime that GUI tools will + * allow the user to specify for credentials. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the minimum credential lifetime for GUI credential lifetime controls. + * \sa kim_preferences_set_minimum_lifetime() + */ +kim_error kim_preferences_get_minimum_lifetime (kim_preferences in_preferences, + kim_lifetime *out_minimum_lifetime); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_maximum_lifetime a maximum lifetime indicating how large a lifetime the + * GUI tools should allow the user to specify for credentials. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the maximum credential lifetime for GUI credential lifetime controls. + * \sa kim_preferences_get_maximum_lifetime() + */ +kim_error kim_preferences_set_maximum_lifetime (kim_preferences io_preferences, + kim_lifetime in_maximum_lifetime); + +/*! + * \param in_preferences a preferences object. + * \param out_maximum_lifetime on exit, the maximum lifetime that GUI tools will + * allow the user to specify for credentials. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the maximum credential lifetime for GUI credential lifetime controls. + * \sa kim_preferences_set_maximum_lifetime() + */ +kim_error kim_preferences_get_maximum_lifetime (kim_preferences in_preferences, + kim_lifetime *out_maximum_lifetime); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_minimum_renewal_lifetime a minimum lifetime indicating how small a lifetime the + * GUI tools should allow the user to specify for + * credential renewal. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the minimum credential renewal lifetime for GUI credential lifetime controls. + * \sa kim_preferences_get_minimum_renewal_lifetime() + */ +kim_error kim_preferences_set_minimum_renewal_lifetime (kim_preferences io_preferences, + kim_lifetime in_minimum_renewal_lifetime); + +/*! + * \param in_preferences a preferences object. + * \param out_minimum_renewal_lifetime on exit, the minimum lifetime that GUI tools will + * allow the user to specify for credential renewal. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the minimum credential renewal lifetime for GUI credential lifetime controls. + * \sa kim_preferences_set_minimum_renewal_lifetime() + */ +kim_error kim_preferences_get_minimum_renewal_lifetime (kim_preferences in_preferences, + kim_lifetime *out_minimum_renewal_lifetime); + +/*! + * \param io_preferences a preferences object to modify. + * \param in_maximum_renewal_lifetime a maximum lifetime indicating how large a lifetime the + * GUI tools should allow the user to specify for + * credential renewal. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the maximum credential renewal lifetime for GUI credential lifetime controls. + * \sa kim_preferences_get_minimum_renewal_lifetime() + */ +kim_error kim_preferences_set_maximum_renewal_lifetime (kim_preferences io_preferences, + kim_lifetime in_maximum_renewal_lifetime); + +/*! + * \param in_preferences a preferences object. + * \param out_maximum_renewal_lifetime on exit, the maximum lifetime that GUI tools will + * allow the user to specify for credential renewal. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the maximum credential renewal lifetime for GUI credential lifetime controls. + * \sa kim_preferences_set_minimum_renewal_lifetime() + */ +kim_error kim_preferences_get_maximum_renewal_lifetime (kim_preferences in_preferences, + kim_lifetime *out_maximum_renewal_lifetime); + +/*! + * \param in_preferences a preferences object. + * \param out_number_of_identities on exit, the number of identities in \a in_preferences. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the number of favorite identities in a preferences object. + */ +kim_error kim_preferences_get_number_of_favorite_identities (kim_preferences in_preferences, + kim_count *out_number_of_identities); + +/*! + * \param in_preferences a preferences object. + * \param in_index a index into the identities list (starting at 0). + * \param out_identity on exit, the identity at \a in_index in \a in_preferences. + * Must be freed with kim_string_free(). + * \param out_options on exit, the options associated with identity at \a in_index + * in \a in_favorite_identities. May be KIM_OPTIONS_DEFAULT. + * Pass NULL if you do not want the options associated with the identity. + * Must be freed with kim_options_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the Nth favorite identity in a preferences object. + */ +kim_error kim_preferences_get_favorite_identity_at_index (kim_preferences in_preferences, + kim_count in_index, + kim_identity *out_identity, + kim_options *out_options); + +/*! + * \param io_preferences a preferences object. + * \param in_identity an identity to add to \a io_preferences. + * \param in_options options which will be associated with that identity. + * Use KIM_OPTIONS_DEFAULT if the identity should use + * the user's default options. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Add a favorite identity to a preferences object. + */ +kim_error kim_preferences_add_favorite_identity (kim_preferences io_preferences, + kim_identity in_identity, + kim_options in_options); + +/*! + * \param io_preferences a preferences object. + * \param in_identity an identity to remove from \a io_preferences. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Remove a favorite identity from a preferences object. + */ +kim_error kim_preferences_remove_favorite_identity (kim_preferences io_preferences, + kim_identity in_identity); + +/*! + * \param io_preferences a preferences object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Remove all favorite identities in a preferences object. + */ +kim_error kim_preferences_remove_all_favorite_identities (kim_preferences io_preferences); + +/*! + * \param in_preferences a preferences object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Synchronize a preferences object with the user's preferences, writing pending changes + * and reading any changes applied by other processes. + */ +kim_error kim_preferences_synchronize (kim_preferences in_preferences); + +/*! + * \param io_preferences the preferences object to be freed. Set to NULL on exit. + * \brief Free memory associated with a preferences object. + */ +void kim_preferences_free (kim_preferences *io_preferences); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_PREFERENCES_H */ diff --git a/krb5-1-7/src/include/kim/kim_selection_hints.h b/krb5-1-7/src/include/kim/kim_selection_hints.h new file mode 100644 index 000000000..1abbd0211 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_selection_hints.h @@ -0,0 +1,438 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_SELECTION_HINTS_H +#define KIM_SELECTION_HINTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + * \page kim_selection_hints_overview KIM Selection Hints Overview + * + * \section kim_selection_hints_introduction Introduction + * + * Most users belong to multiple organizations and thus need + * to authenticate to multiple Kerberos realms. Traditionally Kerberos sites + * solved this problem by setting up a cross-realm relationship, which allowed + * the user to use TGT credentials for their client identity in one realm + * to obtain credentials in another realm via cross-realm authentication. As a + * result users could acquire credentials for a single client identity and use + * them everywhere. + * + * Setting up cross-realm requires that realms share a secret, so sites must + * coordinate with one another to set up a cross-realm relationship. In + * addition, sites must set up authorization policies for users from other + * realms. As Kerberos becomes increasingly wide-spread, many realms will + * not have cross-realm relationships, and users will need to + * manually obtain credentials for their client identity at each realm + * (eg: "user@BANK.COM", "user@UNIVERSITY.EDU", etc). As a result, users + * will often have multiple credentials caches, one for each client identity. + * + * Unfortunately this presents a problem for applications which need to obtain + * service credentials. Which client identity should they use? + * Rather than having each application to manually search the cache collection, + * KIM provides a selection hints API for choosing the best client identity. + * This API is intended to simplify the process of choosing credentials + * and provide consistent behavior across all applications. + * + * Searching the cache collection for credentials may be expensive if there + * are a large number of caches. If credentials for the client identity + * are expired or not present, KIM may also wish to prompt the user for + * new credentials for the appropriate client identity. As a result, + * applications might want to remember which client identity worked in + * the past and always request credentials using that identity. + * + * + * \section kim_selection_hints_creating Creating KIM Selection Hints + * + * A KIM selection hints object consists of an application identifier and one or + * more pieces of information about the service the client application will be + * contacting. The application identifier is used by user preferences + * to control how applications share cache entries. It is important to be + * consistent about what application identifier you provide. Java-style + * identifiers are recommended to avoid collisions. + * + * \section kim_selection_hints_searching Selection Hint Search Behavior + * + * When using selection hints to search for an appropriate client identity, + * KIM uses a consistent hint search order. This allows applications to specify + * potentially contradictory information without preventing KIM from locating a + * single ccache. In addition the selection hint search order may change, + * especially if more hints are added. + * + * As a result, callers are encouraged to provide all relevant search hints, + * even if only a subset of those search hints are necessary to get reasonable + * behavior in the current implementation. Doing so will provide the most + * user-friendly selection experience. + * + * Currently the search order looks like this: + * + * \li Service Identity The client identity which has obtained a service credential for this service identity. + * \li Server A client identity which has obtained a service credential for this server. + * \li Service Realm A client identity which has obtained a service credential for this realm. + * \li Service A client identity which has obtained a service credential for this service. + * \li Client Realm A client identity in this realm. + * \li User A client identity whose first component is this user string. + * + * For example, if you specify a service identity and a credential for + * that identity already exists in the ccache collection, KIM may use that + * ccache, even if your user and client realm entries in the selection hints would + * lead it to choose a different ccache. If no credentials for the service identity + * exist then KIM will fall back on the user and realm hints. + * + * \note Due to performance and information exposure concerns, currently all + * searching is done by examining the cache collection. In the future the KIM + * may also make network requests as part of its search algorithm. For example + * it might check to see if the TGT credentials in each ccache can obtain + * credentials for the service identity specified by the selection hints. + * + * \section kim_selection_hints_selecting Selecting an Identity Using Selection Hints + * + * Once you have provided search criteria for selecting an identity, use + * #kim_selection_hints_get_identity() to obtain an identity object. + * You can then use #kim_identity_get_string() to obtain a krb5 principal + * string for use with gss_import_name() and gss_acquire_cred(). Alternatively, + * you can use #kim_ccache_create_from_client_identity() to obtain a ccache + * containing credentials for the identity. + * + * \note #kim_selection_hints_get_identity() obtains an identity based on + * the current state of the selection hints object. If you change the + * selection hints object you must call #kim_selection_hints_get_identity() + * again. + * + * \section kim_selection_hints_caching Selection Hint Caching Behavior + * + * In addition to using selection hints to search for an appropriate client + * identity, KIM can also use them to remember which client identity worked. + * KIM maintains a per-user cache mapping selection hints to identities so + * that applications do not have to maintain their own caches or present + * user interface for selecting which cache to use. + * + * When #kim_selection_hints_get_identity() is called KIM looks up in the + * cache and returns the identity which the selection hints map to. If + * there is not a preexisting cache entry for the selection hints then + * #kim_selection_hints_get_identity() will search for an identity and + * prompt the user if it cannot find an appropriate one. + * + * If the client identity returned by KIM authenticates and passes + * authorization checks, you should tell KIM to cache the identity by calling + * #kim_selection_hints_remember_identity(). This will create a cache entry + * for the mapping between your selection hints and the identity so that + * subsequent calls to #kim_selection_hints_get_identity() do not need to + * prompt the user. + * + * If the client identity returned by KIM fails to authenticate or fails + * authorization checks, you must call #kim_selection_hints_forget_identity() + * to remove any mapping that already exists. After this function is called, + * future calls to #kim_selection_hints_get_identity() will search for an + * identity again. You may also wish to call this function if the user + * changes your application preferences such that the identity might be + * invalidated. + * + * \note It is very important that you call #kim_selection_hints_forget_identity() + * if your application fails to successfully establish a connection with the + * server. Otherwise the user can get "stuck" using the same non-working + * identity if they chose the wrong one accidentally or if their identity + * information changes. Because only your application understands the + * authorization checksof the protocol it uses, KIM cannot tell whether or not + * the identity worked. + * + * If you wish to search and prompt for an identity without using + * the cached mappings, you can turn off the cached mapping lookups using + * #kim_selection_hints_set_remember_identity(). This is not recommended + * for most applications since it will result in a lot of unnecessary + * searching and prompting for identities. + * + * \note Because cache entries key off of selection hints, it is important + * to always specify the same hints when contacting a particular + * service. Otherwise KIM will not always find the cache entries. + * + * \section kim_selection_hints_prompt Selection Hint Prompting Behavior + * + * If valid credentials for identity in the selection hints cache are + * unavailable or if no identity could be found using searching or caching + * when #kim_selection_hints_get_identity() is called, KIM may present a + * GUI to ask the user to select an identity or acquire credentials for + * an identity. + * + * \note Because of the caching behavior described above the user will + * only be prompted to choose an identity when setting up the application + * or when their identity stops working. + * + * In order to let the user know why Kerberos needs their assistance, KIM + * displays the name of the application which requested the identity + * selection. Unfortunately, some platforms do not provide a runtime + * mechanism for determining the name of the calling process. If your + * application runs on one of these platforms (or is cross-platform) + * you should provide a localized version of its name with + * the private function #kim_library_set_application_name(). + * + * In many cases a single application may select different identities for + * different purposes. For example an email application might use different + * identities to check mail for different accounts. If your application + * has this property you may need to provide the user with a localized + * string describing how the identity will be used. You can specify + * this string with #kim_selection_hints_get_explanation(). You can find + * out what string will be used with kim_selection_hints_set_explanation(). + * + * Since the user may choose to acquire credentials when selection an + * identity, KIM also provides #kim_selection_hints_set_options() to + * set what credential acquisition options are used. + * #kim_selection_hints_get_options() returns the options which will be used. + * + * If you need to disable user interaction, use + * #kim_selection_hints_set_allow_user_interaction(). Use + * #kim_selection_hints_get_allow_user_interaction() to find out whether or + * not user interaction is enabled. User interaction is enabled by default. + * + * See \ref kim_selection_hints_reference for information on specific APIs. + */ + +/*! + * \defgroup kim_selection_hints_reference KIM Selection Hints Reference Documentation + * @{ + */ + +/*! A client identity in this realm. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_client_realm "kim_hint_key_client_realm" + +/*! A client identity whose first component is this user string. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_user "kim_hint_key_user" + +/*! A client identity which has obtained a service credential for this realm. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_service_realm "kim_hint_key_service_realm" + +/*! A client identity which has obtained a service credential for this service. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_service "kim_hint_key_service" + +/*! A client identity which has obtained a service credential for this server. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_server "kim_hint_key_server" + +/*! The client identity which has obtained a service credential for this service identity. + * See \ref kim_selection_hints_overview for more information */ +#define kim_hint_key_service_identity "kim_hint_key_service_identity" + +/*! + * \param out_selection_hints on exit, a new selection hints object. + * Must be freed with kim_selection_hints_free(). + * \param in_application_identifier an application identifier string. Java-style identifiers are recommended + * to avoid cache entry collisions (eg: "com.example.MyApplication") + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Create a new selection hints object. + */ +kim_error kim_selection_hints_create (kim_selection_hints *out_selection_hints, + kim_string in_application_identifier); + +/*! + * \param out_selection_hints on exit, a new selection hints object which is a copy of in_selection_hints. + * Must be freed with kim_selection_hints_free(). + * \param in_selection_hints a selection hints object. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a selection hints object. + */ +kim_error kim_selection_hints_copy (kim_selection_hints *out_selection_hints, + kim_selection_hints in_selection_hints); + +/*! + * \param io_selection_hints a selection hints object to modify. + * \param in_hint_key A string representing the type of hint to set. + * \param in_hint_string A string representation of a hint for + * \a in_hint_key to set in \a in_selection_hints. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the string value of a hint used for identity selection. + * \sa kim_selection_hints_get_hint() + */ +kim_error kim_selection_hints_set_hint (kim_selection_hints io_selection_hints, + kim_string in_hint_key, + kim_string in_hint_string); + +/*! + * \param in_selection_hints a selection hints object. + * \param in_hint_key A string representing the type of hint to + * obtain. + * \param out_hint_string On exit, a string representation of the hint + * \a in_hint_key in \a in_selection_hints. + * If the hint is not set, sets the value pointed + * to by \a out_hint_string to NULL; + * Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the string value of a hint used for identity selection. + * \sa kim_selection_hints_set_hint() + */ +kim_error kim_selection_hints_get_hint (kim_selection_hints in_selection_hints, + kim_string in_hint_key, + kim_string *out_hint_string); + +/*! + * \param io_selection_hints a selection hints object to modify. + * \param in_explanation a localized string describing why the caller needs the identity. + * \note If the application only does one thing (the reason it needs an identity is obvious) + * then you may not need to call this function. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the strings used to prompt the user to select the identity. + * \sa kim_selection_hints_get_explanation() + */ +kim_error kim_selection_hints_set_explanation (kim_selection_hints io_selection_hints, + kim_string in_explanation); + +/*! + * \param in_selection_hints a selection hints object. + * \param out_explanation on exit, the localized string specified in \a in_selection_hints + * which describes why the caller needs the identity. May be NULL. + * If non-NULL, must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the strings used to prompt the user to select the identity. + * \sa kim_selection_hints_set_explanation() + */ +kim_error kim_selection_hints_get_explanation (kim_selection_hints in_selection_hints, + kim_string *out_explanation); + + +/*! + * \param io_selection_hints a selection hints object to modify. + * \param in_options options to control credential acquisition. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Set the options which will be used if credentials need to be acquired. + * \sa kim_selection_hints_get_options() + */ +kim_error kim_selection_hints_set_options (kim_selection_hints io_selection_hints, + kim_options in_options); + +/*! + * \param in_selection_hints a selection hints object. + * \param out_options on exit, the options to control credential acquisition + * specified in \a in_selection_hints. May be KIM_OPTIONS_DEFAULT. + * If not, must be freed with kim_options_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get the options which will be used if credentials need to be acquired. + * \sa kim_selection_hints_set_options() + */ +kim_error kim_selection_hints_get_options (kim_selection_hints in_selection_hints, + kim_options *out_options); + +/*! + * \param in_selection_hints a selection hints object to modify + * \param in_allow_user_interaction a boolean value specifying whether or not KIM should ask + * the user to select an identity for \a in_selection_hints. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This setting defaults to TRUE. + * \brief Set whether or not KIM may interact with the user to select an identity. + * \sa kim_selection_hints_get_allow_user_interaction + */ +kim_error kim_selection_hints_set_allow_user_interaction (kim_selection_hints in_selection_hints, + kim_boolean in_allow_user_interaction); + +/*! + * \param in_selection_hints a selection hints object to modify + * \param out_allow_user_interaction on exit, a boolean value specifying whether or not KIM + * should ask the user to select an identity for + * \a in_selection_hints. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This setting defaults to TRUE. + * \brief Get whether or not KIM may interact with the user to select an identity. + * \sa kim_selection_hints_set_allow_user_interaction + */ +kim_error kim_selection_hints_get_allow_user_interaction (kim_selection_hints in_selection_hints, + kim_boolean *out_allow_user_interaction); + +/*! + * \param in_selection_hints a selection hints object to modify + * \param in_remember_identity a boolean value specifying whether or not KIM should use a cached + * mapping between \a in_selection_hints and a Kerberos identity. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This setting defaults to TRUE. + * \brief Set whether or not KIM will use cached mappings for this selection hints object. + * \sa kim_selection_hints_get_remember_identity + */ +kim_error kim_selection_hints_set_remember_identity (kim_selection_hints in_selection_hints, + kim_boolean in_remember_identity); + +/*! + * \param in_selection_hints a selection hints object to modify + * \param out_remember_identity on exit, a boolean value specifying whether or not KIM will use a + * cached mapping between \a in_selection_hints and a Kerberos identity. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note This setting defaults to TRUE. + * \brief Get whether or not KIM will use cache mappings for this selection hints object. + * \sa kim_selection_hints_set_remember_identity + */ +kim_error kim_selection_hints_get_remember_identity (kim_selection_hints in_selection_hints, + kim_boolean *out_remember_identity); + +/*! + * \param in_selection_hints the selection hints to add to the cache. + * \param out_identity the Kerberos identity \a in_selection_hints maps to. + * Must be freed with kim_identity_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \note \a out_identity is the identity mapped to by the current state of \a in_selection_hints. + * This function may prompt the user via a GUI to choose that identity. + * Subsequent modifications to \a in_selection_hints will not change \a out_identity. + * \brief Choose a client identity based on selection hints. + */ + +kim_error kim_selection_hints_get_identity (kim_selection_hints in_selection_hints, + kim_identity *out_identity); + +/*! + * \param in_selection_hints the selection hints to add to the cache. + * \param in_identity the Kerberos identity \a in_selection_hints maps to. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Add an entry for the selection hints to the selection hints cache, + * replacing any existing entry. + */ + +kim_error kim_selection_hints_remember_identity (kim_selection_hints in_selection_hints, + kim_identity in_identity); + +/*! + * \param in_selection_hints the selection hints to remove from the cache. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Remove an entry for the selection hints from the selection hints cache. + */ + +kim_error kim_selection_hints_forget_identity (kim_selection_hints in_selection_hints); + +/*! + * \param io_selection_hints the selection hints object to be freed. Set to NULL on exit. + * \brief Free memory associated with a selection hints object. + */ + +void kim_selection_hints_free (kim_selection_hints *io_selection_hints); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_SELECTION_HINTS_H */ diff --git a/krb5-1-7/src/include/kim/kim_string.h b/krb5-1-7/src/include/kim/kim_string.h new file mode 100644 index 000000000..f68f4a409 --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_string.h @@ -0,0 +1,122 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_STRING_H +#define KIM_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + * \page kim_string_overview KIM String Overview + * + * A UTF8 string. + * + * Memory management routines are provided for runtime consistency on + * operating systems with shared libraries and multiple runtimes. + * + * \section kim_string_error_messages KIM Error Messages + * + * Like most C APIs, the KIM API returns numeric error codes. These error + * codes may come from KIM, krb5 or GSS APIs. In most cases the caller will + * want to handle these error programmatically. However, in some circumstances + * the caller may wish to print an error string to the user. + * + * One problem with just printing the error code to the user is that frequently + * the context behind the error has been lost. For example if KIM is trying to + * obtain credentials via referrals, it may fail partway through the process. + * In this case the error code will be KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, which + * maps to "Client not found in Kerberos database". Unfortunately this error + * isn't terribly helpful because it doesn't tell the user whether they typoed + * their principal name or if referrals failed. + * + * To avoid this problem, KIM maintains an explanatory string for the last + * error seen in each thread calling into KIM. If a caller wishes to display + * an error to the user, immediately after getting the error the caller should + * call #kim_string_create_for_last_error() to obtain a copy of the + * descriptive error message. + * + * See \ref kim_string_reference for information on specific APIs. + */ + +/*! + * \defgroup kim_string_reference KIM String Reference Documentation + * @{ + */ + +/*! + * \param out_string On success, a human-readable UTF-8 string describing the + * error representedby \a in_error. Must be freed with + * kim_string_free(). + * \param in_error an error code. Used to verify that the correct error + * string will be returned (see note below). + * \return On success, KIM_NO_ERROR. + * \note This API is implemented using thread local storage. It should be + * called immediately after a KIM API returns an error code so that the correct + * string is returned. The returned copy may then be held by the caller until + * needed. If \a in_error does not match the last saved error KIM may return + * a less descriptive string. + * \brief Get a text description of an error suitable for display to the user. + */ +kim_error kim_string_create_for_last_error (kim_string *out_string, + kim_error in_error); + +/*! + * \param out_string on exit, a new string object which is a copy of \a in_string. + Must be freed with kim_string_free(). + * \param in_string the string to copy. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Copy a string. + */ +kim_error kim_string_copy (kim_string *out_string, + const kim_string in_string); + +/*! + * \param in_string a string. + * \param in_compare_to_string a string to be compared to \a in_string. + * \param out_comparison on exit, a comparison result indicating whether \a in_string + * is greater than, less than or equal to \a in_compare_to_string. + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Compare two strings. + */ +kim_error kim_string_compare (kim_string in_string, + kim_string in_compare_to_string, + kim_comparison *out_comparison); + +/*! + * \param io_string a string to be freed. Set to NULL on exit. + * \brief Free memory associated with a string. + */ +void kim_string_free (kim_string *io_string); + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_STRING_H */ diff --git a/krb5-1-7/src/include/kim/kim_types.h b/krb5-1-7/src/include/kim/kim_types.h new file mode 100644 index 000000000..a871410bb --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_types.h @@ -0,0 +1,155 @@ +/* + * Copyright 2005-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. + */ + +#ifndef KIM_TYPES_H +#define KIM_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \defgroup kim_types_reference KIM Types and Constants + * @{ + */ + +/*! + * The KIM Error type. + */ +typedef int32_t kim_error; + +/*! + * No error value for the kim_error type. + */ +#define KIM_NO_ERROR ((kim_error) 0) + +/*! + * A time value represented in seconds since January 1, 1970. + */ +typedef int64_t kim_time; + +/*! + * A duration represented in seconds. + */ +typedef int64_t kim_lifetime; + +/*! + * An quantity, usually used to return the number of elements in an array. + */ +typedef uint64_t kim_count; + +/*! + * A boolean value. 0 means false, all other values mean true. + */ +typedef int kim_boolean; + +/*! + * A comparison between two sortable objects. + * \li Less than 0 means the first object is less than the second. + * \li 0 means the two objects are identical. + * \li Greater than 0 means the first object is greater than the second. + * \note Convenience macros are provided for interpreting #kim_comparison + * values to improve code readability. + * See #kim_comparison_is_less_than(), #kim_comparison_is_equal_to() and + * #kim_comparison_is_greater_than() + */ +typedef int kim_comparison; + +/*! + * Convenience macro for interpreting #kim_comparison. + */ +#define kim_comparison_is_less_than(c) (c < 0) + +/*! + * Convenience macro for interpreting #kim_comparison. + */ +#define kim_comparison_is_equal_to(c) (c == 0) + +/*! + * Convenience macro for interpreting #kim_comparison. + */ +#define kim_comparison_is_greater_than(c) (c > 0) + +/*! + * The KIM String type. See \ref kim_string_overview for more information. + */ +typedef const char *kim_string; + +struct kim_identity_opaque; +/*! + * A KIM Principal object. See \ref kim_identity_overview for more information. + */ +typedef struct kim_identity_opaque *kim_identity; + +struct kim_options_opaque; +/*! + * A KIM Options object. See \ref kim_options_overview for more information. + */ +typedef struct kim_options_opaque *kim_options; + +struct kim_selection_hints_opaque; +/*! + * A KIM Selection Hints object. See \ref kim_selection_hints_overview for more information. + */ +typedef struct kim_selection_hints_opaque *kim_selection_hints; + +struct kim_preferences_opaque; +/*! + * A KIM Preferences object. See \ref kim_preferences_overview for more information. + */ +typedef struct kim_preferences_opaque *kim_preferences; + +struct kim_ccache_iterator_opaque; +/*! + * A KIM CCache Iterator object. See \ref kim_credential_cache_collection for more information. + */ +typedef struct kim_ccache_iterator_opaque *kim_ccache_iterator; + +struct kim_ccache_opaque; +/*! + * A KIM CCache object. See \ref kim_ccache_overview for more information. + */ +typedef struct kim_ccache_opaque *kim_ccache; + +struct kim_credential_iterator_opaque; +/*! + * A KIM Credential Iterator object. See \ref kim_credential_iterator for more information. + */ +typedef struct kim_credential_iterator_opaque *kim_credential_iterator; + +struct kim_credential_opaque; +/*! + * A KIM Credential object. See \ref kim_credential_overview for more information. + */ +typedef struct kim_credential_opaque *kim_credential; + +/*!@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_TYPES_H */ diff --git a/krb5-1-7/src/include/kim/kim_ui_plugin.h b/krb5-1-7/src/include/kim/kim_ui_plugin.h new file mode 100644 index 000000000..a15aa419a --- /dev/null +++ b/krb5-1-7/src/include/kim/kim_ui_plugin.h @@ -0,0 +1,152 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_UI_PLUGIN_H +#define KIM_UI_PLUGIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * The type of prompt which needs to be displayed. + * This value determines what type of user interface is displayed. + * See \ref kim_options_custom_prompt_callback for more information. + */ +typedef uint32_t kim_prompt_type; + +enum kim_prompt_type_enum { + kim_prompt_type_password = 0, + kim_prompt_type_preauth = 1 +}; + +/* + * Plugins for Controlling Identity Selection and Credential Acquisition + * + * In order to acquire credentials, Kerberos needs to obtain one or more secrets from the user. + * These secrets may be a certificate, password, SecurID pin, or information from a smart card. + * If obtaining the secret requires interaction with the user, the Kerberos libraries call a + * "prompter callback" to display a dialog or command line prompt to request information from + * the user. If you want to provide your own custom dialogs or command line prompts, + * the KIM APIs provide a plugin mechanism for replacing the default prompt ui with your own. + * + * The function table / structure which a KIM ui plugin module must export + * as "kim_ui_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. + */ +/* extern kim_ui_plugin_ftable_v0 kim_ui_0; */ + + +typedef struct kim_ui_plugin_ftable_v0 { + int minor_version; /* currently 0 */ + + /* Called before other calls to allow the UI to initialize. + * Return an error if you can't display your UI in this environment. + * To allow your plugin to be called from multiple threads, pass back + * state associated with this instance of your UI in out_context. + * The same context pointer will be provided to all plugin calls for + * this ui. */ + kim_error (*init) (void **out_context); + + /* Present UI which allows the user to enter a new identity. + * This is typically called when the user selects a "new tickets" + * control or menu item from a ticket management utility. + * If this UI calls into KIM to get new credentials it may + * call auth_prompt below. + * If out_change_password is set to TRUE, KIM will call change_password + * on the identity and then call enter_identity again, allowing you + * to have a change password option on your UI. */ + kim_error (*enter_identity) (void *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password); + + /* Present UI to select which identity to use. + * This is typically called the first time an application tries to use + * Kerberos and is used to establish a hints preference for the application. + * If this UI calls into KIM to get new credentials it may + * call auth_prompt below. + * If out_change_password is set to TRUE, KIM will call change_password + * on the identity and then call select_identity again, allowing you + * to have a change password option on your UI. */ + kim_error (*select_identity) (void *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password); + + /* Present UI to display authentication to the user */ + /* If in_allow_save_reply is FALSE do not display UI to allow the user + * to save their password. In this case the value of out_save_reply will + * be ignored. */ + kim_error (*auth_prompt) (void *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply); + + /* Prompt to change the identity's password. + * May be combined with an auth_prompt if additional auth is required, + * eg: SecurID pin. + * If in_old_password_expired is true, this callback is in response + * to an expired password error. If this is the case the same context + * which generated the error will be used for this callback. */ + kim_error (*change_password) (void *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); + + /* Display an error to the user; may be called after any of the prompts */ + kim_error (*handle_error) (void *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); + + /* Free strings returned by the UI. Will be called once for each string + * returned from a plugin callback. If you have returned a string twice + * just make sure your free function checks for NULL and sets the pointer + * to NULL when done freeing memory. */ + void (*free_string) (void *in_context, + char **io_string); + + /* Called after the last prompt (even on error) to allow the UI to + * free allocated resources associated with its context. */ + kim_error (*fini) (void *io_context); + +} kim_ui_plugin_ftable_v0; + + +#ifdef __cplusplus +} +#endif + +#endif /* KIM_UI_PLUGIN_H */ diff --git a/krb5-1-7/src/include/krb5.h b/krb5-1-7/src/include/krb5.h new file mode 100644 index 000000000..d68965155 --- /dev/null +++ b/krb5-1-7/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 diff --git a/krb5-1-7/src/include/krb5/authdata_plugin.h b/krb5-1-7/src/include/krb5/authdata_plugin.h new file mode 100644 index 000000000..e8c9fce2d --- /dev/null +++ b/krb5-1-7/src/include/krb5/authdata_plugin.h @@ -0,0 +1,160 @@ +/* + * krb5/authdata_plugin.h + * + * Copyright (C) 2007 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * AuthorizationData plugin definitions for Kerberos 5. + */ + +/* + * This is considered an INTERNAL interface at this time. + * + * Some work is needed before exporting it: + * + * + Documentation. + * + Sample code. + * + Test cases (preferably automated testing under "make check"). + * + Hook into TGS exchange too; will change API. + * + Examine memory management issues, especially for Windows; may + * change API. + * + * Other changes that would be nice to have, but not necessarily + * before making this interface public: + * + * + Library support for AD-IF-RELEVANT and similar wrappers. (We can + * make the plugin construct them if it wants them.) + * + KDC could combine/optimize wrapped AD elements provided by + * multiple plugins, e.g., two IF-RELEVANT sequences could be + * merged. (The preauth plugin API also has this bug, we're going + * to need a general fix.) + */ + +#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED +#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED +#include + +/* + * While arguments of these types are passed-in, for the most part a + * authorization data module can treat them as opaque. If we need + * keying data, we can ask for it directly. + */ +struct _krb5_db_entry_new; + +/* + * The function table / structure which an authdata server module must export as + * "authdata_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. + */ +/* extern krb5plugin_authdata_ftable_v0 authdata_server_0; */ +typedef struct krb5plugin_authdata_ftable_v0 { + /* Not-usually-visible name. */ + char *name; + + /* + * 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. + */ + krb5_error_code (*init_proc)(krb5_context, void **); + void (*fini_proc)(krb5_context, void *); + /* + * Actual authorization data handling function. If this field + * holds a null pointer, this mechanism will be skipped, and the + * init/fini functions will not be run. + * + * This function should only modify the field + * enc_tkt_reply->authorization_data. All other values should be + * considered inputs only. And, it should *modify* the field, not + * overwrite it and assume that there are no other authdata + * plugins in use. + * + * Memory management: authorization_data is a malloc-allocated, + * null-terminated sequence of malloc-allocated pointers to + * authorization data structures. This plugin code currently + * assumes the libraries, KDC, and plugin all use the same malloc + * pool, which may be a problem if/when we get the KDC code + * running on Windows. + * + * If this function returns a non-zero error code, a message + * is logged, but no other action is taken. Other authdata + * plugins will be called, and a response will be sent to the + * client (barring other problems). + */ + krb5_error_code (*authdata_proc)(krb5_context, + struct _krb5_db_entry_new *client, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply); +} krb5plugin_authdata_ftable_v0; + +typedef struct krb5plugin_authdata_ftable_v1 { + /* Not-usually-visible name. */ + char *name; + + /* + * 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. + */ + krb5_error_code (*init_proc)(krb5_context, void **); + void (*fini_proc)(krb5_context, void *); + /* + * Actual authorization data handling function. If this field + * holds a null pointer, this mechanism will be skipped, and the + * init/fini functions will not be run. + * + * This function should only modify the field + * enc_tkt_reply->authorization_data. All other values should be + * considered inputs only. And, it should *modify* the field, not + * overwrite it and assume that there are no other authdata + * plugins in use. + * + * Memory management: authorization_data is a malloc-allocated, + * null-terminated sequence of malloc-allocated pointers to + * authorization data structures. This plugin code currently + * assumes the libraries, KDC, and plugin all use the same malloc + * pool, which may be a problem if/when we get the KDC code + * running on Windows. + * + * If this function returns a non-zero error code, a message + * is logged, but no other action is taken. Other authdata + * plugins will be called, and a response will be sent to the + * client (barring other problems). + */ + krb5_error_code (*authdata_proc)(krb5_context, + unsigned int flags, + struct _krb5_db_entry_new *client, + struct _krb5_db_entry_new *server, + struct _krb5_db_entry_new *tgs, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); +} krb5plugin_authdata_ftable_v1; + +#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */ diff --git a/krb5-1-7/src/include/krb5/krb5.hin b/krb5-1-7/src/include/krb5/krb5.hin new file mode 100644 index 000000000..bf8c29c59 --- /dev/null +++ b/krb5-1-7/src/include/krb5/krb5.hin @@ -0,0 +1,2633 @@ +/* -*- c -*- + * include/krb5.h + * + * Copyright 1989,1990,1995,2001, 2003, 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. + * + * + * 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 + +#if defined(__MACH__) && defined(__APPLE__) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +#if defined(_MSDOS) || defined(_WIN32) +#include +#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 +#include /* for *_MAX */ +#include + +#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 + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 30203 +# define KRB5_ATTR_DEPRECATED __attribute__((deprecated)) +#elif defined _WIN32 +# define KRB5_ATTR_DEPRECATED __declspec(deprecated) +#else +# define KRB5_ATTR_DEPRECATED +#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_cryptotype; + +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 +/* PKINIT */ +#define KRB5_NT_X500_PRINCIPAL 6 +/* Name in form of SMTP email name */ +#define KRB5_NT_SMTP_NAME 7 +/* Windows 2000 UPN */ +#define KRB5_NT_ENTERPRISE_PRINCIPAL 10 +/* Windows 2000 UPN and SID */ +#define KRB5_NT_MS_PRINCIPAL -128 +/* NT 4 style name */ +#define KRB5_NT_MS_PRINCIPAL_AND_ID -129 +/* NT 4 style name and SID */ +#define KRB5_NT_ENT_PRINCIPAL_AND_ID -130 + +/* 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_NETBIOS 0x0014 +#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; + +typedef struct _krb5_crypto_iov { + krb5_cryptotype flags; + krb5_data data; +} krb5_crypto_iov; + +/* 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 +/* PKINIT */ +#define ENCTYPE_DSA_SHA1_CMS 0x0009 /* DSA with SHA1, CMS signature */ +#define ENCTYPE_MD5_RSA_CMS 0x000a /* MD5 with RSA, CMS signature */ +#define ENCTYPE_SHA1_RSA_CMS 0x000b /* SHA1 with RSA, CMS signature */ +#define ENCTYPE_RC2_CBC_ENV 0x000c /* RC2 cbc mode, CMS enveloped data */ +#define ENCTYPE_RSA_ENV 0x000d /* RSA encryption, CMS enveloped data */ +#define ENCTYPE_RSA_ES_OAEP_ENV 0x000e /* RSA w/OEAP encryption, CMS enveloped data */ +#define ENCTYPE_DES3_CBC_ENV 0x000f /* DES-3 cbc mode, CMS enveloped data */ + +#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_MD5_HMAC_ARCFOUR -137 /*Microsoft netlogon cksumtype*/ +#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_fx_cf2_simple(krb5_context context, + krb5_keyblock *k1, const char *pepper1, + krb5_keyblock *k2, const char *pepper2, + krb5_keyblock **out); + /* Returns KRB-FX-CF2 in a newly allocated + * keyblock on success or an error code on error. + * This function is simple in that it assumes + * pepper1 and pepper2 are C strings with no + * internal nulls and that the enctype of the + * result will be the same as that of k1. Both + * of these assumptions are true of current + * specs. + */ + + +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 */ +/* define in draft-ietf-krb-wg-preauth-framework*/ +#define KRB5_KEYUSAGE_FAST_REQ_CHKSUM 50 +#define KRB5_KEYUSAGE_FAST_ENC 51 +#define KRB5_KEYUSAGE_FAST_REP 52 +#define KRB5_KEYUSAGE_FAST_FINISHED 53 +#define KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT 54 +#define KRB5_KEYUSAGE_ENC_CHALLENGE_KDC 55 + +#define KRB5_KEYUSAGE_FAST_REP 52 +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); + +/* AEAD APIs */ +#define KRB5_CRYPTO_TYPE_EMPTY 0 /* [in] ignored */ +#define KRB5_CRYPTO_TYPE_HEADER 1 /* [out] header */ +#define KRB5_CRYPTO_TYPE_DATA 2 /* [in, out] plaintext */ +#define KRB5_CRYPTO_TYPE_SIGN_ONLY 3 /* [in] associated data */ +#define KRB5_CRYPTO_TYPE_PADDING 4 /* [out] padding */ +#define KRB5_CRYPTO_TYPE_TRAILER 5 /* [out] checksum for encrypt */ +#define KRB5_CRYPTO_TYPE_CHECKSUM 6 /* [out] checksum for MIC */ +#define KRB5_CRYPTO_TYPE_STREAM 7 /* [in] entire message */ + +krb5_error_code KRB5_CALLCONV + krb5_c_make_checksum_iov + (krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *key, krb5_keyusage usage, + krb5_crypto_iov *data, size_t num_data); + +krb5_error_code KRB5_CALLCONV + krb5_c_verify_checksum_iov + (krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_boolean *valid); + +krb5_error_code KRB5_CALLCONV + krb5_c_encrypt_iov + (krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + +krb5_error_code KRB5_CALLCONV + krb5_c_decrypt_iov + (krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + +krb5_error_code KRB5_CALLCONV + krb5_c_crypto_length + (krb5_context context, krb5_enctype enctype, + krb5_cryptotype type, unsigned int *size); + +krb5_error_code KRB5_CALLCONV + krb5_c_crypto_length_iov + (krb5_context context, krb5_enctype enctype, + krb5_crypto_iov *data, size_t num_data); + +krb5_error_code KRB5_CALLCONV + krb5_c_padding_length + (krb5_context context, krb5_enctype enctype, + size_t data_length, unsigned int *size); + +#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); + +#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_CNAME_IN_ADDL_TKT 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_ETYPE_NEGOTIATION 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 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_SVR_REFERRAL_INFO 20 /* Windows 2000 referrals */ +#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_PADATA_PAC_REQUEST 128 /* include Windows PAC */ +#define KRB5_PADATA_FOR_USER 129 /* username protocol transition request */ +#define KRB5_PADATA_S4U_X509_USER 130 /* certificate protocol transition request */ +#define KRB5_PADATA_FX_COOKIE 133 +#define KRB5_PADATA_FX_FAST 136 +#define KRB5_PADATA_FX_ERROR 137 +#define KRB5_PADATA_ENCRYPTED_CHALLENGE 138 + +#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 +#define KRB5_AUTHDATA_WIN2K_PAC 128 +#define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /* RFC 4537 */ +#define KRB5_AUTHDATA_FX_ARMOR 71 +/* 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 */ + /* the following field is added in March 2009; it is a hack so + * that FAST state can be carried to pre-authentication plugins. + * A new plugin interface may be a better long-term approach. It + * is believed to be safe to extend this structure because it is + * not found in any public APIs. + */ + void * kdc_state; +} 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_pa_data **enc_padata; /* Windows 2000 compat */ +} 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 */ +/* + * Note for Windows 2000 compatibility this is encoded + * in the enc_padata field of the krb5_enc_kdc_rep_part. + */ +typedef struct _krb5_pa_svr_referral_data { + /* Referred name, only realm is required */ + krb5_principal principal; +} krb5_pa_svr_referral_data; + +typedef struct _krb5_pa_server_referral_data { + krb5_data *referred_realm; + krb5_principal true_principal_name; + krb5_principal requested_principal_name; + krb5_timestamp referral_valid_until; + krb5_checksum rep_cksum; +} krb5_pa_server_referral_data; + +typedef struct _krb5_pa_pac_req { + /* TRUE if a PAC should be included in TGS-REP */ + krb5_boolean include_pac; +} krb5_pa_pac_req; + +/* + * 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_cc_move (krb5_context context, krb5_ccache src, krb5_ccache dst); + +krb5_error_code KRB5_CALLCONV +krb5_cc_last_change_time ( + krb5_context context, + krb5_ccache ccache, + krb5_timestamp *change_time); + +krb5_error_code KRB5_CALLCONV +krb5_cc_lock (krb5_context context, krb5_ccache ccache); + +krb5_error_code KRB5_CALLCONV +krb5_cc_unlock (krb5_context context, krb5_ccache ccache); + + +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_cccol_last_change_time(krb5_context context, krb5_timestamp *change_time); + +krb5_error_code KRB5_CALLCONV +krb5_cccol_lock(krb5_context context); + +krb5_error_code KRB5_CALLCONV +krb5_cccol_unlock(krb5_context context); + +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; + +struct _krb5_kt; +typedef struct _krb5_kt *krb5_keytab; + +const 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 *); + +krb5_error_code KRB5_CALLCONV +krb5_set_default_tgs_enctypes + (krb5_context, + const krb5_enctype *); + +krb5_error_code KRB5_CALLCONV krb5_get_permitted_enctypes + (krb5_context, krb5_enctype **); + +krb5_boolean KRB5_CALLCONV krb5_is_thread_safe(void); + +/* libkrb.spec */ + +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 */ +#define KRB5_GC_CANONICALIZE 4 /* set canonicalize KDC option */ + +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 **); +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_mk_rep_dce + (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_rd_rep_dce + (krb5_context, + krb5_auth_context, + const krb5_data *, + krb5_ui_4 *); +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 * ); +#define KRB5_PRINCIPAL_PARSE_NO_REALM 0x1 +#define KRB5_PRINCIPAL_PARSE_REQUIRE_REALM 0x2 +#define KRB5_PRINCIPAL_PARSE_ENTERPRISE 0x4 +krb5_error_code KRB5_CALLCONV krb5_parse_name_flags + (krb5_context, + const char *, + int, + 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 *); +#define KRB5_PRINCIPAL_UNPARSE_SHORT 0x1 +#define KRB5_PRINCIPAL_UNPARSE_NO_REALM 0x2 +#define KRB5_PRINCIPAL_UNPARSE_DISPLAY 0x4 +krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags + (krb5_context, + krb5_const_principal, + int, + char **); +krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags_ext + (krb5_context, + krb5_const_principal, + int, + 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_boolean KRB5_CALLCONV krb5_principal_compare_any_realm + (krb5_context, + krb5_const_principal, + krb5_const_principal); +#define KRB5_PRINCIPAL_COMPARE_IGNORE_REALM 1 +#define KRB5_PRINCIPAL_COMPARE_ENTERPRISE 2 /* compare UPNs as real principals */ +#define KRB5_PRINCIPAL_COMPARE_CASEFOLD 4 /* case-insensitive comparison */ +#define KRB5_PRINCIPAL_COMPARE_UTF8 8 /* treat principals as UTF-8 */ + +krb5_boolean KRB5_CALLCONV krb5_principal_compare_flags + (krb5_context, + krb5_const_principal, + krb5_const_principal, + int); +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 *); +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_merge_authdata + (krb5_context, + krb5_authdata * const *, + krb5_authdata *const *, + krb5_authdata ***); +/* Merge two authdata arrays, such as the array from a ticket + * and authenticator */ + +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 **); +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 *, ...) +#if __GNUC__ >= 4 + __attribute__ ((sentinel)) +#endif + ; +#if KRB5_DEPRECATED +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_build_principal_va + (krb5_context, + krb5_principal, unsigned int, const char *, va_list); +#endif + +/* Version of krb5_build_principal_va which allocates krb5_principal_data */ +krb5_error_code KRB5_CALLCONV krb5_build_principal_alloc_va + (krb5_context, krb5_principal *, unsigned int, const char *, va_list); + +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 */ +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 * ); +/* 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 *); +/* 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 *); + +krb5_error_code KRB5_CALLCONV krb5_cc_copy_creds + (krb5_context context, + krb5_ccache incc, + krb5_ccache outcc); + + +/* krb5_free.c */ +void KRB5_CALLCONV krb5_free_principal + (krb5_context, krb5_principal ); +void KRB5_CALLCONV krb5_free_authenticator + (krb5_context, krb5_authenticator * ); +void KRB5_CALLCONV krb5_free_addresses + (krb5_context, krb5_address ** ); +void KRB5_CALLCONV krb5_free_authdata + (krb5_context, krb5_authdata ** ); +void KRB5_CALLCONV krb5_free_ticket + (krb5_context, krb5_ticket * ); +void KRB5_CALLCONV krb5_free_error + (krb5_context, krb5_error * ); +void KRB5_CALLCONV krb5_free_creds + (krb5_context, krb5_creds *); +void KRB5_CALLCONV krb5_free_cred_contents + (krb5_context, krb5_creds *); +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 *); +void KRB5_CALLCONV krb5_free_ap_rep_enc_part + (krb5_context, krb5_ap_rep_enc_part *); +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); + +krb5_error_code KRB5_CALLCONV +krb5_get_profile + (krb5_context, struct _profile_t * /* profile_t */ *); + +#if KRB5_DEPRECATED +KRB5_ATTR_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_ATTR_DEPRECATED 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_ATTR_DEPRECATED 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_ATTR_DEPRECATED 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 */ + +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 **); + +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 *); + +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 *); + +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_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_auth_con_getlocalsubkey + (krb5_context, + krb5_auth_context, + krb5_keyblock **); + +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_auth_con_getremotesubkey + (krb5_context, + krb5_auth_context, + krb5_keyblock **); +#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_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_auth_con_initivector + (krb5_context, + krb5_auth_context); +#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 *); + +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 + */ + +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 * ); +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); +krb5_error_code KRB5_CALLCONV krb5_set_real_time + (krb5_context, krb5_timestamp, krb5_int32); + +krb5_error_code KRB5_CALLCONV krb5_get_time_offsets + (krb5_context, krb5_timestamp *, krb5_int32 *); + +/* 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 +#define KRB5_GET_INIT_CREDS_OPT_CANONICALIZE 0x0200 + + +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_canonicalize +(krb5_get_init_creds_opt *opt, + int canonicalize); + +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_opt_set_fast_ccache_name +(krb5_context context, krb5_get_init_creds_opt *opt, + const char * fast_ccache_name); + /* This API sets a ccache name that will contain some TGT on + calls to get_init_creds functions. If set, this ccache will + be used for FAST (draft-ietf-krb-wg-preauth-framework) to + protect the AS-REQ from observation and active attack. If + the fast_ccache_name is set, then FAST may be required by the + client library. In this version FAST is required.*/ +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); + +/* + * 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 *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; +void KRB5_CALLCONV +krb5_vset_error_message (krb5_context, krb5_error_code, const char *, va_list) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; +void KRB5_CALLCONV +krb5_copy_error_message (krb5_context, krb5_context); + +/* + * 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); + +krb5_error_code KRB5_CALLCONV +krb5_decode_authdata_container(krb5_context context, + krb5_authdatatype type, + const krb5_authdata *container, + krb5_authdata ***authdata); +krb5_error_code KRB5_CALLCONV +krb5_encode_authdata_container(krb5_context context, + krb5_authdatatype type, + krb5_authdata * const*authdata, + krb5_authdata ***container); + +/* + * Windows PAC + */ +struct krb5_pac_data; +typedef struct krb5_pac_data *krb5_pac; + +krb5_error_code KRB5_CALLCONV +krb5_pac_add_buffer +(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_data *data); + +void KRB5_CALLCONV +krb5_pac_free +(krb5_context context, + krb5_pac pac); + +krb5_error_code KRB5_CALLCONV +krb5_pac_get_buffer +(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + krb5_data *data); + +krb5_error_code KRB5_CALLCONV +krb5_pac_get_types +(krb5_context context, + krb5_pac pac, + size_t *len, + krb5_ui_4 **types); + +krb5_error_code KRB5_CALLCONV +krb5_pac_init +(krb5_context context, + krb5_pac *pac); + +krb5_error_code KRB5_CALLCONV +krb5_pac_parse +(krb5_context context, + const void *ptr, + size_t len, + krb5_pac *pac); + +krb5_error_code KRB5_CALLCONV +krb5_pac_verify +(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr); + +#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 + +#undef KRB5_ATTR_DEPRECATED + +#endif /* KRB5_GENERAL__ */ diff --git a/krb5-1-7/src/include/krb5/locate_plugin.h b/krb5-1-7/src/include/krb5/locate_plugin.h new file mode 100644 index 000000000..f9f29baf7 --- /dev/null +++ b/krb5-1-7/src/include/krb5/locate_plugin.h @@ -0,0 +1,60 @@ +/* + * + * + * 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 + +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-7/src/include/krb5/preauth_plugin.h b/krb5-1-7/src/include/krb5/preauth_plugin.h new file mode 100644 index 000000000..e11913e3f --- /dev/null +++ b/krb5-1-7/src/include/krb5/preauth_plugin.h @@ -0,0 +1,526 @@ +/* + * + * + * 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 + +/* + * 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 expected to be used to encrypt the + * encrypted portion of the AS_REP packet. When handling a + * PREAUTH_REQUIRED error, this typically comes from etype-info2. + * When handling an AS reply, it is initialized from the AS reply itself.*/ + krb5plugin_preauth_client_get_etype = 1, + /* Free the data returned from krb5plugin_preauth_client_req_get_etype */ + krb5plugin_preauth_client_free_etype = 2, + /* The returned krb5_data contains the FAST armor key in a + * krb5_keyblock. Returns success with a NULL data item in the + * krb5_data if the client library supports FAST but is not using it.*/ + krb5plugin_preauth_client_fast_armor = 3, + /* Frees return from KRB5PLUGIN_PREAUTH_CLIENT_FAST_ARMOR. It is + * acceptable to set data to NULL and free the keyblock using + * krb5_free_keyblock; in that case, this frees the krb5_data + * only.*/ +krb5plugin_preauth_client_free_fast_armor = 4, +}; +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, + /* The returned krb5_data contains a krb5_keyblock with the FAST + armor key. The data member is NULL if this method is not part + of a FAST tunnel */ + krb5plugin_preauth_fast_armor = 5, + /* Frees a fast armor key; it is acceptable to set data to NULL + and free the keyblock using krb5_free_keyblock; in that case, + this function simply frees the data*/ + krb5plugin_preauth_free_fast_armor = 6, + }; + +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-7/src/include/krb54proto.h b/krb5-1-7/src/include/krb54proto.h new file mode 100644 index 000000000..d1d16e1ba --- /dev/null +++ b/krb5-1-7/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-7/src/include/osconf.hin b/krb5-1-7/src/include/osconf.hin new file mode 100644 index 000000000..339e4b228 --- /dev/null +++ b/krb5-1-7/src/include/osconf.hin @@ -0,0 +1,140 @@ +/* -*- c -*- + * include/krb5/stock/osconf.h + * + * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#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" +#define KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosAuthDataPlugins" +#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 KRB5_DEFAULT_SUPPORTED_ENCTYPES \ + "aes256-cts-hmac-sha1-96:normal " \ + "aes128-cts-hmac-sha1-96:normal " \ + "des3-cbc-sha1:normal arcfour-hmac-md5:normal" + +#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" + +/* + * 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_KPROP "@SBINDIR/kprop" +#define KPROPD_DEFAULT_KRB_DB DEFAULT_KDB_FILE +#define KPROPD_ACL_FILE "@LOCALSTATEDIR/krb5kdc/kpropd.acl" + +/* + * GSS mechglue + */ +#define MECH_CONF "@SYSCONFDIR/gss/mech" +#define MECH_LIB_PREFIX "@GSSMODULEDIR/" + +#endif /* KRB5_OSCONF__ */ diff --git a/krb5-1-7/src/include/pkinit_apple_utils.h b/krb5-1-7/src/include/pkinit_apple_utils.h new file mode 100644 index 000000000..313955f39 --- /dev/null +++ b/krb5-1-7/src/include/pkinit_apple_utils.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_utils.h - PKINIT utilities, Mac OS X version + * + * Created 19 May 2004 by Doug Mitchell. + */ + +#ifndef _PKINIT_APPLE_UTILS_H_ +#define _PKINIT_APPLE_UTILS_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PKI_DEBUG +#define PKI_DEBUG 0 +#endif + +#if PKI_DEBUG + +#include + +#define pkiDebug(args...) printf(args) +#define pkiCssmErr(str, rtn) cssmPerror(str, rtn) +#else +#define pkiDebug(args...) +#define pkiCssmErr(str, rtn) +#endif /* PKI_DEBUG */ + +/* + * Macros used to initialize a declared CSSM_DATA and krb5_data to zero/NULL values. + */ +#define INIT_CDATA(cd) cd = {0, NULL} +#define INIT_KDATA(kd) kd = {0, 0, NULL} + +/* attach/detach to/from CL */ +CSSM_RETURN pkiClDetachUnload(CSSM_CL_HANDLE clHand); +CSSM_CL_HANDLE pkiClStartup(void); + +/* + * CSSM_DATA <--> krb5_ui_4 + */ +krb5_error_code pkiDataToInt( + const CSSM_DATA *cdata, + krb5_int32 *i); /* RETURNED */ + +krb5_error_code pkiIntToData( + krb5_int32 num, + CSSM_DATA *cdata, /* allocated in coder space and RETURNED */ + SecAsn1CoderRef coder); + +/* + * raw data --> krb5_data + */ +krb5_error_code pkiDataToKrb5Data( + const void *data, + unsigned dataLen, + krb5_data *kd); /* content mallocd and RETURNED */ + +/* + * CSSM_DATA <--> krb5_data + * + * CSSM_DATA data is managed by a SecAsn1CoderRef; krb5_data.data is mallocd. + */ +krb5_error_code pkiCssmDataToKrb5Data( + const CSSM_DATA *cd, + krb5_data *kd); /* content mallocd and RETURNED */ + + +krb5_error_code pkiKrb5DataToCssm( + const krb5_data *kd, + CSSM_DATA *cdata, /* allocated in coder space and RETURNED */ + SecAsn1CoderRef coder); + +/* + * CFDataRef --> krb5_data, mallocing the destination contents. + */ +krb5_error_code pkiCfDataToKrb5Data( + CFDataRef cfData, + krb5_data *kd); /* content mallocd and RETURNED */ + +/* + * Non-mallocing conversion between CSSM_DATA and krb5_data + */ +#define PKI_CSSM_TO_KRB_DATA(cd, kd) \ + (kd)->data = (char *)(cd)->Data; \ + (kd)->length = (cd)->Length; + +#define PKI_KRB_TO_CSSM_DATA(kd, cd) \ + (cd)->Data = (uint8 *)(kd)->data; \ + (cd)->Length = (kd)->length; + +/* + * Compare to CSSM_DATAs. Return TRUE if they're the same else FALSE. + */ +krb5_boolean pkiCompareCssmData( + const CSSM_DATA *d1, + const CSSM_DATA *d2); + +/* + * krb5_timestamp <--> a mallocd string in generalized format + */ +krb5_error_code pkiKrbTimestampToStr( + krb5_timestamp kts, + char **str); /* mallocd and RETURNED */ + +krb5_error_code pkiTimeStrToKrbTimestamp( + const char *str, + unsigned len, + krb5_timestamp *kts); /* RETURNED */ + +/* + * How many items in a NULL-terminated array of pointers? + */ +unsigned pkiNssArraySize( + const void **array); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_APPLE_UTILS_H_ */ diff --git a/krb5-1-7/src/include/pkinit_asn1.h b/krb5-1-7/src/include/pkinit_asn1.h new file mode 100644 index 000000000..b90ae5960 --- /dev/null +++ b/krb5-1-7/src/include/pkinit_asn1.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_asn1.h - ASN.1 encode/decode routines for PKINIT + * + * Created 18 May 2004 by Doug Mitchell. + */ + +#ifndef _PKINIT_ASN1_H_ +#define _PKINIT_ASN1_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* RFC 3280 AlgorithmIdentifier */ +typedef struct { + krb5_data algorithm; /* OID */ + krb5_data parameters; /* ASN_ANY, defined by algorithm */ +} krb5int_algorithm_id; + +/* + * Encode and decode AuthPack, public key version (no Diffie-Hellman components). + */ +krb5_error_code krb5int_pkinit_auth_pack_encode( + krb5_timestamp kctime, + krb5_int32 cusec, /* microseconds */ + krb5_ui_4 nonce, + const krb5_checksum *pa_checksum, + const krb5int_algorithm_id *cms_types, /* optional */ + krb5_ui_4 num_cms_types, + krb5_data *auth_pack); /* mallocd and RETURNED */ + +/* all returned values are optional - pass NULL if you don't want them */ +krb5_error_code krb5int_pkinit_auth_pack_decode( + const krb5_data *auth_pack, /* DER encoded */ + krb5_timestamp *kctime, /* RETURNED */ + krb5_ui_4 *cusec, /* microseconds, RETURNED */ + krb5_ui_4 *nonce, /* RETURNED */ + krb5_checksum *pa_checksum, /* contents mallocd and RETURNED */ + krb5int_algorithm_id **cms_types, /* mallocd and RETURNED */ + krb5_ui_4 *num_cms_types); /* RETURNED */ + + +/* + * Given DER-encoded issuer and serial number, create an encoded + * IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_issuer_serial_encode( + const krb5_data *issuer, /* DER encoded */ + const krb5_data *serial_num, + krb5_data *issuer_and_serial); /* content mallocd and RETURNED */ + +/* + * Decode IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_issuer_serial_decode( + const krb5_data *issuer_and_serial, /* DER encoded */ + krb5_data *issuer, /* DER encoded, RETURNED */ + krb5_data *serial_num); /* RETURNED */ + +/* + * Top-level encode for PA-PK-AS-REQ. + * The signed_auth_pack field is wrapped in an OCTET STRING, content + * specific tag 0, during encode. + */ +krb5_error_code krb5int_pkinit_pa_pk_as_req_encode( + const krb5_data *signed_auth_pack, /* DER encoded ContentInfo */ + const krb5_data *trusted_CAs, /* optional: trustedCertifiers. Contents are + * DER-encoded issuer/serialNumbers. */ + krb5_ui_4 num_trusted_CAs, + const krb5_data *kdc_cert, /* optional kdcPkId, DER encoded issuer/serial */ + krb5_data *pa_pk_as_req); /* mallocd and RETURNED */ + +/* + * Top-level decode for PA-PK-AS-REQ. Does not perform cert verification on the + * ContentInfo; that is returned in BER-encoded form and processed elsewhere. + * The OCTET STRING wrapping the signed_auth_pack field is removed during the + * decode. + */ +krb5_error_code krb5int_pkinit_pa_pk_as_req_decode( + const krb5_data *pa_pk_as_req, + krb5_data *signed_auth_pack, /* DER encoded ContentInfo, RETURNED */ + /* + * Remainder are optionally RETURNED (specify NULL for pointers to + * items you're not interested in). + */ + krb5_ui_4 *num_trusted_CAs, /* sizeof trusted_CAs */ + krb5_data **trusted_CAs, /* mallocd array of DER-encoded TrustedCAs + * issuer/serial */ + krb5_data *kdc_cert); /* DER encoded issuer/serial */ + +/* + * Encode a ReplyKeyPack. The result is used as the Content of a SignedData. + */ +krb5_error_code krb5int_pkinit_reply_key_pack_encode( + const krb5_keyblock *key_block, + const krb5_checksum *checksum, + krb5_data *reply_key_pack); /* mallocd and RETURNED */ + +/* + * Decode a ReplyKeyPack. + */ +krb5_error_code krb5int_pkinit_reply_key_pack_decode( + const krb5_data *reply_key_pack, + krb5_keyblock *key_block, /* RETURNED */ + krb5_checksum *checksum); /* contents mallocd and RETURNED */ + +/* + * Encode a PA-PK-AS-REP. + * Exactly one of {dh_signed_data, enc_key_pack} is non-NULL on entry; + * each is a previously encoded item. + * + * dh_signed_data, if specified, is an encoded DHRepInfo. + * enc_key_pack, if specified, is EnvelopedData(signedData(ReplyKeyPack) + */ +krb5_error_code krb5int_pkinit_pa_pk_as_rep_encode( + const krb5_data *dh_signed_data, + const krb5_data *enc_key_pack, /* EnvelopedData(signedData(ReplyKeyPack) */ + krb5_data *pa_pk_as_rep); /* mallocd and RETURNED */ + +/* + * Decode a PA-PK-AS-REP. + * On successful return, exactly one of {dh_signed_data, enc_key_pack} + * will be non-NULL, each of which is mallocd and must be freed by + * caller. + * + * dh_signed_data, if returned, is an encoded DHRepInfo. + * enc_key_pack, if specified, is EnvelopedData(signedData(ReplyKeyPack) + */ +krb5_error_code krb5int_pkinit_pa_pk_as_rep_decode( + const krb5_data *pa_pk_as_rep, + krb5_data *dh_signed_data, + krb5_data *enc_key_pack); + +/* + * Given a DER encoded certificate, obtain the associated IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_get_issuer_serial( + const krb5_data *cert, + krb5_data *issuer_and_serial); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_ASN1_H_ */ diff --git a/krb5-1-7/src/include/pkinit_cert_store.h b/krb5-1-7/src/include/pkinit_cert_store.h new file mode 100644 index 000000000..6811d5a72 --- /dev/null +++ b/krb5-1-7/src/include/pkinit_cert_store.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_cert_store.h - PKINIT certificate storage/retrieval utilities + * + * Created 26 May 2004 by Doug Mitchell at Apple. + */ + +#ifndef _PKINIT_CERT_STORE_H_ +#define _PKINIT_CERT_STORE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Opaque reference to a machine-dependent representation of a certificate + * which is capable of signing. On Mac OS X this is actually a SecIdentityRef. + */ +typedef void *krb5_pkinit_signing_cert_t; + +/* + * Opaque reference to a machine-dependent representation of a certificate. + * On Mac OS X this is actually a SecCertificateRef. + */ +typedef void *krb5_pkinit_cert_t; + +/* + * Opaque reference to a database in which PKINIT-related certificates are stored. + */ +typedef void *krb5_pkinit_cert_db_t; + +/* + * Obtain signing cert for specified principal. On successful return, + * caller must eventually release the cert with krb5_pkinit_release_cert(). + * + * Returns KRB5_PRINC_NOMATCH if client cert not found. + */ +krb5_error_code krb5_pkinit_get_client_cert( + const char *principal, /* full principal string */ + krb5_pkinit_signing_cert_t *client_cert); /* RETURNED */ + +/* + * Determine if the specified client has a signing cert. Returns TRUE + * if so, else returns FALSE. + */ +krb5_boolean krb5_pkinit_have_client_cert( + const char *principal); /* full principal string */ + +/* + * Store the specified certificate (or, more likely, some platform-dependent + * reference to it) as the specified principal's signing cert. Passing + * in NULL for the client_cert has the effect of deleting the relevant entry + * in the cert storage. + */ +krb5_error_code krb5_pkinit_set_client_cert_from_signing_cert( + const char *principal, /* full principal string */ + krb5_pkinit_signing_cert_t client_cert); +krb5_error_code krb5_pkinit_set_client_cert( + const char *principal, /* full principal string */ + krb5_pkinit_cert_t client_cert); + +/* + * Obtain a reference to the client's cert database. Specify either principal + * name or client_cert as obtained from krb5_pkinit_get_client_cert(). + */ +krb5_error_code krb5_pkinit_get_client_cert_db( + const char *principal, /* optional, full principal string */ + krb5_pkinit_signing_cert_t client_cert, /* optional, from krb5_pkinit_get_client_cert() */ + krb5_pkinit_cert_db_t *client_cert_db); /* RETURNED */ + +/* + * Obtain the KDC signing cert, with optional CA and specific cert specifiers. + * CAs and cert specifiers are in the form of DER-encoded issuerAndSerialNumbers. + * + * The client_spec argument is typically provided by the client as kdcPkId. + * + * If trusted_CAs and client_spec are NULL, a platform-dependent preferred + * KDC signing cert is returned, if one exists. + * + * On successful return, caller must eventually release the cert with + * krb5_pkinit_release_cert(). Outside of an unusual test configuration this = + * + * Returns KRB5_PRINC_NOMATCH if KDC cert not found. + * + */ +krb5_error_code krb5_pkinit_get_kdc_cert( + krb5_ui_4 num_trusted_CAs, /* sizeof *trusted_CAs */ + krb5_data *trusted_CAs, /* optional */ + krb5_data *client_spec, /* optional */ + krb5_pkinit_signing_cert_t *kdc_cert); /* RETURNED */ + +/* + * Obtain a reference to the KDC's cert database. + */ +krb5_error_code krb5_pkinit_get_kdc_cert_db( + krb5_pkinit_cert_db_t *kdc_cert_db); /* RETURNED */ + +/* + * Release certificate references obtained via krb5_pkinit_get_client_cert() and + * krb5_pkinit_get_kdc_cert(). + */ +extern void krb5_pkinit_release_cert( + krb5_pkinit_signing_cert_t cert); + +/* + * Release database references obtained via krb5_pkinit_get_client_cert_db() and + * krb5_pkinit_get_kdc_cert_db(). + */ +extern void krb5_pkinit_release_cert_db( + krb5_pkinit_cert_db_t cert_db); + +/* + * Obtain a mallocd C-string representation of a certificate's SHA1 digest. + * Only error is a NULL return indicating memory failure. + * Caller must free the returned string. + */ +char *krb5_pkinit_cert_hash_str( + const krb5_data *cert); + +/* + * Obtain a client's optional list of trusted KDC CA certs (trustedCertifiers) + * and/or trusted KDC cert (kdcPkId) for a given client and server. + * All returned values are mallocd and must be freed by caller; the contents + * of the krb5_datas are DER-encoded certificates. + */ +krb5_error_code krb5_pkinit_get_server_certs( + const char *client_principal, + const char *server_principal, + krb5_data **trusted_CAs, /* RETURNED, though return value may be NULL */ + krb5_ui_4 *num_trusted_CAs, /* RETURNED */ + krb5_data *kdc_cert); /* RETURNED, though may be 0/NULL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_CERT_STORE_H_ */ diff --git a/krb5-1-7/src/include/pkinit_client.h b/krb5-1-7/src/include/pkinit_client.h new file mode 100644 index 000000000..31951caaf --- /dev/null +++ b/krb5-1-7/src/include/pkinit_client.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_client.h - Client side routines for PKINIT + * + * Created 20 May 2004 by Doug Mitchell at Apple. + */ + +#ifndef _PKINIT_CLIENT_H_ +#define _PKINIT_CLIENT_H_ + +#include +#include "pkinit_cms.h" +#include "pkinit_cert_store.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Create a PA-PK-AS-REQ message. + */ +krb5_error_code krb5int_pkinit_as_req_create( + krb5_context context, + krb5_timestamp kctime, + krb5_int32 cusec, /* microseconds */ + krb5_ui_4 nonce, + const krb5_checksum *cksum, + krb5_pkinit_signing_cert_t client_cert, /* required! */ + + /* + * trusted_CAs correponds to PA-PK-AS-REQ.trustedCertifiers. + * Expressed here as an optional list of DER-encoded certs. + */ + const krb5_data *trusted_CAs, + krb5_ui_4 num_trusted_CAs, + + /* optional PA-PK-AS-REQ.kdcPkId, expressed here as a + * DER-encoded cert */ + const krb5_data *kdc_cert, + krb5_data *as_req); /* mallocd and RETURNED */ + +/* + * Parse PA-PK-AS-REP message. Optionally evaluates the message's certificate chain. + * Optionally returns various components. + */ +krb5_error_code krb5int_pkinit_as_rep_parse( + krb5_context context, + const krb5_data *as_rep, + krb5_pkinit_signing_cert_t client_cert, /* required for decryption */ + krb5_keyblock *key_block, /* RETURNED */ + krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ + /* contents mallocd and RETURNED */ + krb5int_cert_sig_status *cert_status, /* RETURNED */ + + /* + * Cert fields, all optionally RETURNED. + * + * signer_cert is the DER-encoded leaf cert from the incoming SignedData. + * all_certs is an array of all of the certs in the incoming SignedData, + * in full DER-encoded form. + */ + krb5_data *signer_cert, /* content mallocd */ + unsigned *num_all_certs, /* sizeof *all_certs */ + krb5_data **all_certs); /* krb5_data's and their content mallocd */ + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_CLIENT_H_ */ diff --git a/krb5-1-7/src/include/pkinit_cms.h b/krb5-1-7/src/include/pkinit_cms.h new file mode 100644 index 000000000..6e5fb96ce --- /dev/null +++ b/krb5-1-7/src/include/pkinit_cms.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_cms.h - CMS encode/decode routines, Mac OS X version + * + * Created 19 May 2004 by Doug Mitchell at Apple. + */ + +#ifndef _PKINIT_CMS_H_ +#define _PKINIT_CMS_H_ + +#include +#include "pkinit_cert_store.h" /* for krb5_pkinit_signing_cert_t */ +#include "pkinit_asn1.h" /* for krb5int_algorithm_id */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define ContentType for a SignedData and EnvelopedData. + */ +enum { + /* normal CMS ContentTypes */ + ECT_Data, + ECT_SignedData, + ECT_EnvelopedData, + ECT_EncryptedData, + + /* + * For SignedAuthPack + * pkauthdata: { iso (1) org (3) dod (6) internet (1) + * security (5) kerberosv5 (2) pkinit (3) pkauthdata (1)} + */ + ECT_PkAuthData, + + /* + * For ReplyKeyPack + * pkrkeydata: { iso (1) org (3) dod (6) internet (1) + * security (5) kerberosv5 (2) pkinit (3) pkrkeydata (3) } + */ + ECT_PkReplyKeyKata, + + /* + * Other - i.e., unrecognized ContentType on decode. + */ + ECT_Other +}; +typedef krb5_int32 krb5int_cms_content_type; + +/* + * Result of certificate and signature verification. + */ +enum { + pki_cs_good = 0, + pki_not_signed, /* message not signed */ + pki_not_evaluated, /* signed, but not evaluated per caller request */ + /* remainder imply good signature on the message proper, i.e., these + * are all certificate errors. */ + pki_cs_sig_verify_fail, /* signature verification failed */ + pki_cs_bad_leaf, /* leaf/subject cert itself is plain bad */ + pki_cs_no_root, /* looks good but not verifiable to any root */ + pki_cs_unknown_root, /* verified to root we don't recognize */ + pki_cs_expired, /* expired */ + pki_cs_not_valid_yet, /* cert not valid yet */ + pki_cs_revoked, /* revoked via CRL or OCSP */ + pki_cs_untrusted, /* marked by user as untrusted */ + pki_bad_cms, /* CMS Format precluded verification */ + pki_bad_key_use, /* Bad ExtendedKeyUse or KeyUsage extension */ + pki_bad_digest, /* unacceptable CMS digest algorithm */ + pki_cs_other_err /* other cert verify error */ +}; +typedef krb5_int32 krb5int_cert_sig_status; + +/* + * Create a CMS message: either encrypted (EnvelopedData), signed + * (SignedData), or both (EnvelopedData(SignedData(content)). + * + * The message is signed iff signing_cert is non-NULL. + * The message is encrypted iff recip_cert is non-NULL. + * + * The content_type argument specifies to the eContentType + * for a SignedData's EncapsulatedContentInfo; it's ignored + * if the message is not to be signed. + * + * The cms_types argument optionally specifies a list, in order + * of decreasing preference, of CMS algorithms to use in the + * creation of the CMS message. + */ +krb5_error_code krb5int_pkinit_create_cms_msg( + const krb5_data *content, /* Content */ + krb5_pkinit_signing_cert_t signing_cert, /* optional: signed by this cert */ + const krb5_data *recip_cert, /* optional: encrypted with this cert */ + krb5int_cms_content_type content_type, /* OID for EncapsulatedData */ + krb5_ui_4 num_cms_types, /* optional */ + const krb5int_algorithm_id *cms_types, /* optional */ + krb5_data *content_info); /* contents mallocd and RETURNED */ + +/* + * Parse a ContentInfo as best we can. All returned fields are optional - + * pass NULL for values you don't need. + * + * If signer_cert_status is NULL on entry, NO signature or cert evaluation + * will be performed. + * + * The is_client_msg argument indicates whether the CMS message originated + * from the client (TRUE) or server (FALSE) and may be used in platform- + * dependent certificate evaluation. + * + * Note that signature and certificate verification errors do NOT cause + * this routine itself to return an error; caller is reponsible for + * handling such errors per the signer_cert_status out parameter. + */ +krb5_error_code krb5int_pkinit_parse_cms_msg( + const krb5_data *content_info, + krb5_pkinit_cert_db_t cert_db, /* may be required for SignedData */ + krb5_boolean is_client_msg, /* TRUE : msg is from client */ + krb5_boolean *is_signed, /* RETURNED */ + krb5_boolean *is_encrypted, /* RETURNED */ + krb5_data *raw_data, /* RETURNED */ + krb5int_cms_content_type *inner_content_type,/* Returned, ContentType of */ + /* EncapsulatedData if */ + /* *is_signed true */ + /* returned for type SignedData only */ + krb5_data *signer_cert, /* RETURNED */ + krb5int_cert_sig_status *signer_cert_status,/* RETURNED */ + unsigned *num_all_certs, /* size of *all_certs RETURNED */ + krb5_data **all_certs); /* entire cert chain RETURNED */ + +/* + * An AuthPack contains an optional set of AlgorithmIdentifiers + * which define the CMS algorithms supported by the client, in + * order of decreasing preference. + * + * krb5int_pkinit_get_cms_types() is a CMS-implementation-dependent + * function returning supported CMS algorithms in the form of a + * pointer and a length suitable for passing to + * krb5int_pkinit_auth_pack_encode. If no preference is to be expressed, + * this function returns NULL/0 (without returning a nonzero krb5_error_code). + * + * krb5int_pkinit_free_cms_types() frees the pointer obtained + * from krb5int_pkinit_get_cms_types() as necessary. + */ +krb5_error_code krb5int_pkinit_get_cms_types( + krb5int_algorithm_id **supported_cms_types, /* RETURNED */ + krb5_ui_4 *num_supported_cms_types); /* RETURNED */ + +krb5_error_code krb5int_pkinit_free_cms_types( + krb5int_algorithm_id *supported_cms_types, + krb5_ui_4 num_supported_cms_types); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_CMS_H_ */ diff --git a/krb5-1-7/src/include/port-sockets.h b/krb5-1-7/src/include/port-sockets.h new file mode 100644 index 000000000..35ed2b4c4 --- /dev/null +++ b/krb5-1-7/src/include/port-sockets.h @@ -0,0 +1,187 @@ +#ifndef _PORT_SOCKET_H +#define _PORT_SOCKET_H +#if defined(_WIN32) + +#include +#include + +/* 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 +typedef int socklen_t; + +#else /* UNIX variants */ + +#include "autoconf.h" + +#include +#include /* For struct sockaddr_in and in_addr */ +#include /* For inet_ntoa */ +#include + +#ifndef HAVE_NETDB_H_H_ERRNO +extern int h_errno; /* In case it's missing, e.g., HP-UX 10.20. */ +#endif + +#include /* For MAXHOSTNAMELEN */ +#include /* For SOCK_*, AF_*, etc */ +#include /* For struct timeval */ +#include /* For struct ifconf, for localaddr.c */ +#ifdef HAVE_SYS_UIO_H +#include /* For struct iovec, for sg_buf */ +#endif +#ifdef HAVE_SYS_FILIO_H +#include /* 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-7/src/include/socket-utils.h b/krb5-1-7/src/include/socket-utils.h new file mode 100644 index 000000000..070bb2ff1 --- /dev/null +++ b/krb5-1-7/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-7/src/include/spnego-asn1.h b/krb5-1-7/src/include/spnego-asn1.h new file mode 100644 index 000000000..8070a9f99 --- /dev/null +++ b/krb5-1-7/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-7/src/include/win-mac.h b/krb5-1-7/src/include/win-mac.h new file mode 100644 index 000000000..f77cd2b41 --- /dev/null +++ b/krb5-1-7/src/include/win-mac.h @@ -0,0 +1,229 @@ +/* + * 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 + +#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 +#include + +#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 +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 _ version. + * The following defines works around this problem. + */ +#include +#include +#include +#include +#include + +#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 + +/* VS2005 has deprecated strdup */ +#ifndef strdup +#define strdup _strdup +#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-7/src/kadmin/Makefile.in b/krb5-1-7/src/kadmin/Makefile.in new file mode 100644 index 000000000..e5b781084 --- /dev/null +++ b/krb5-1-7/src/kadmin/Makefile.in @@ -0,0 +1,8 @@ +thisconfigdir=.. +myfulldir=kadmin +mydir=kadmin +BUILDTOP=$(REL).. +SUBDIRS = cli dbutil passwd ktutil server testing + +all:: + diff --git a/krb5-1-7/src/kadmin/cli/Makefile.in b/krb5-1-7/src/kadmin/cli/Makefile.in new file mode 100644 index 000000000..f02399686 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/Makefile.in @@ -0,0 +1,46 @@ +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 +COMMON_OBJS = kadmin.o kadmin_ct.o ss_wrapper.o getdate.o +KADMIN_OBJS = $(COMMON_OBJS) keytab.o +LOCAL_OBJS = $(COMMON_OBJS) keytab_local.o + +SRCS = kadmin.c kadmin_ct.c ss_wrapper.c getdate.c keytab.c + +LOCALINCLUDES=-I$(srcdir) + +all:: $(PROG).local $(PROG) + +$(PROG).local: $(LOCAL_OBJS) $(SS_DEPLIB) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $(PROG).local $(LOCAL_OBJS) $(SS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) + +$(PROG): $(KADMIN_OBJS) $(SS_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $(PROG) $(KADMIN_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}$(CLIENT_BINDIR)/$(PROG) + $(INSTALL_SCRIPT) $(srcdir)/k5srvutil.sh ${DESTDIR}$(CLIENT_BINDIR)/k5srvutil + $(INSTALL_DATA) $(srcdir)/k5srvutil.M ${DESTDIR}$(CLIENT_MANDIR)/k5srvutil.1 + $(INSTALL_DATA) $(srcdir)/$(PROG).M ${DESTDIR}$(CLIENT_MANDIR)/$(PROG).1 + $(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) $(COMMON_OBJS) $(KADMIN_OBJS) $(LOCAL_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 diff --git a/krb5-1-7/src/kadmin/cli/deps b/krb5-1-7/src/kadmin/cli/deps new file mode 100644 index 000000000..928af0a38 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/deps @@ -0,0 +1,41 @@ +# +# Generated makefile dependencies follow. +# +$(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 \ + $(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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 kadmin.h keytab.c diff --git a/krb5-1-7/src/kadmin/cli/getdate.y b/krb5-1-7/src/kadmin/cli/getdate.y new file mode 100644 index 000000000..530114598 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/getdate.y @@ -0,0 +1,1067 @@ +%{ +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets 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 + +/* 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 +#else +#ifdef _AIX /* for Bison */ + #pragma alloca +#else +void *alloca (); +#endif +#endif +#endif + +#include +#include + +#if defined(HAVE_STDLIB_H) +#include +#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 if that will be used. */ + +#if defined(vms) + +#include +#include + +#else + +#include + +#ifdef TIME_WITH_SYS_TIME +#include +#include +#else +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#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 +#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 tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT +%type tSEC_UNIT tSNUMBER tUNUMBER tZONE +%type 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; + struct tm *tm; + + 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) + Julian -= 60 * 60; + else if (DSTmode == DSTmaybe) { + tm = localtime(&Julian); + if (tm == NULL) + return -1; + else if (tm->tm_isdst) + Julian -= 60 * 60; + } + return Julian; +} + + +static time_t +DSTcorrect(Start, Future, error) + time_t Start; + time_t Future; + int *error; +{ + time_t StartDay; + time_t FutureDay; + struct tm *tm; + + tm = localtime(&Start); + if (tm == NULL) { + *error = 1; + return -1; + } + StartDay = (tm->tm_hour + 1) % 24; + tm = localtime(&Future); + if (tm == NULL) { + *error = 1; + return -1; + } + FutureDay = (tm->tm_hour + 1) % 24; + return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; +} + + +static time_t +RelativeDate(Start, DayOrdinal, DayNumber, error) + time_t Start; + time_t DayOrdinal; + time_t DayNumber; + int *error; +{ + struct tm *tm; + time_t now; + + now = Start; + tm = localtime(&now); + if (tm == NULL) { + *error = 1; + return -1; + } + now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); + now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); + return DSTcorrect(Start, now, error); +} + + +static time_t +RelativeMonth(Start, RelMonth) + time_t Start; + time_t RelMonth; +{ + struct tm *tm; + time_t Month; + time_t Year; + time_t ret; + int error; + + if (RelMonth == 0) + return 0; + tm = localtime(&Start); + if (tm == NULL) + return -1; + 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; + ret = DSTcorrect(Start, ret, &error); + if (error) + return -1; + return 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 +#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; + int error = 0; + + 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. */ + tm = localtime(&ftz.time); + if (tm == NULL) + return -1; + ftz.timezone = difftm (&gmt, tm) / 60; + } + + tm = localtime(&now->time); + if (tm == NULL) + return -1; + 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; + if (error != 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, &error); + if (error != 0) + return -1; + 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-7/src/kadmin/cli/k5srvutil.M b/krb5-1-7/src/kadmin/cli/k5srvutil.M new file mode 100644 index 000000000..528bf00f2 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/k5srvutil.M @@ -0,0 +1,58 @@ +.\" Copyright 1989, 2003 by the Massachusetts Institute of Technology. +.\" +.TH K5SRVUTIL 1 +.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-7/src/kadmin/cli/k5srvutil.sh b/krb5-1-7/src/kadmin/cli/k5srvutil.sh new file mode 100755 index 000000000..e1284e6af --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/cli/kadmin.M b/krb5-1-7/src/kadmin/cli/kadmin.M new file mode 100644 index 000000000..f7109ceb9 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/kadmin.M @@ -0,0 +1,911 @@ +.TH KADMIN 1 +.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. +.PP +kadmin.local can be configured to log updates for incremental database +propagation. Incremental propagation allows slave KDC servers to +receive principal and policy updates incrementally instead of +receiving full dumps of the database. This facility can be enabled in +the +.I kdc.conf +file with the +.I iprop_enable +option. See the +.I kdc.conf +documentation for other options for tuning incremental propagation +parameters. + +.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= +specifies the LDAP server to connect to by a LDAP URI. +.TP +\-x 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. +.TP +\-x bindpwd= +.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= +Specifies the LDAP object that will contain the Kerberos principal being +created. +.TP +\-x linkdn= +.fi +Specifies the LDAP object to which the newly created Kerberos principal object +will point to. +.TP +\-x containerdn= +Specifies the container object under which the Kerberos principal is to be created. +.TP +\-x tktpolicy= +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}\fBok_as_delegate\fP +.B +ok_as_delegate +sets the OK-AS-DELEGATE flag on tickets issued for use with this principal +as the service, which clients may use as a hint that credentials can and +should be delegated when authenticating to the service. (Sets the +.SM KRB5_KDB_OK_AS_DELEGATE +flag.) +.B -ok_as_delegate +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= +Associates a ticket policy to the Kerberos principal. +.TP +\-x linkdn= +.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 +[\fB\-norandkey\fP] [[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP] +.br +Adds a principal or all principals matching +.I princ-exp +to a keytab. +It randomizes each principal's key in the process, to prevent a +compromised admin account from reading out all of the keys from the +database. However, +.B kadmin.local +has the +.B \-norandkey +option, which leaves the keys and their version numbers unchanged, +similar to the Kerberos V4 +.B ext_srvtab +command. +That allows users to continue to use the passwords they know +to login normally, while simultaneously allowing scripts +to login to the same account using a keytab. +There is no significant security risk added since +.B kadmin.local +must be run by root on the KDC anyway. +.sp +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'.kadm5.lock\ \ 'u" +principal.db +default name for Kerberos principal database +.TP +.kadm5 +KADM5 administrative database. (This would be "principal.kadm5", if you +use the default database name.) Contains policy information. +.TP +.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-7/src/kadmin/cli/kadmin.c b/krb5-1-7/src/kadmin/cli/kadmin.c new file mode 100644 index 000000000..d7fff1307 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/kadmin.c @@ -0,0 +1,1858 @@ +/* + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* for "_" macro */ +#include "k5-platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include "kadmin.h" + +#if defined(USE_KIM) +#include +#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 }, +{"ok_as_delegate", 14, KRB5_KDB_OK_AS_DELEGATE, 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 */ + "UNKNOWN_0x00010000", /* 0x00010000 */ + "UNKNOWN_0x00020000", /* 0x00020000 */ + "UNKNOWN_0x00040000", /* 0x00040000 */ + "UNKNOWN_0x00080000", /* 0x00080000 */ + "OK_AS_DELEGATE", /* 0x00100000 */ +}; + +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; + snprintf(out, sizeof(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; + int result; + + /* assumes def_realm is initialized! */ + cp = strchr(name, '@'); + while (cp) { + if (cp - name && *(cp - 1) != '\\') + break; + else + cp = strchr(cp + 1, '@'); + } + if (cp == NULL) + result = asprintf(&fullname, "%s@%s", name, def_realm); + else + result = asprintf(&fullname, "%s", name); + if (result < 0) + return ENOMEM; + 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_KIM) + /* Turn off all password prompting from the KLL */ + retval = kim_library_set_allow_automatic_prompting (0); + if (retval) { + com_err(whoami, retval, + "while calling kim_library_set_allow_automatic_prompting()"); + 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) + free(db_name); + asprintf(&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: 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'; + if (asprintf(&princstr, "%s/admin%s%s", canon, + (realm) ? "@" : "", + (realm) ? realm : "") < 0) { + fprintf(stderr, "%s: out of memory\n", whoami); + exit(1); + } + free(canon); + krb5_free_principal(context, princ); + freeprinc++; + } else if ((luser = getenv("USER"))) { + if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) { + fprintf(stderr, "%s: out of memory\n", whoami); + exit(1); + } + freeprinc++; + } else if ((pw = getpwuid(getuid()))) { + if (asprintf(&princstr, "%s/admin@%s", pw->pw_name, + def_realm) < 0) { + fprintf(stderr, "%s: out of memory\n", whoami); + exit(1); + } + 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; + } + + if ((retval = kadm5_init_iprop(handle, 0)) != 0) { + com_err(whoami, retval, _("while mapping update log")); + exit(1); + } + + 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 deleting 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; + + snprintf(prompt1, sizeof(prompt1), + "Enter password for principal \"%.900s\"", + *argv); + snprintf(prompt2, sizeof(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, +#if APPLE_PKINIT + cert_hash, +#endif /* APPLE_PKINIT */ + 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; +#if APPLE_PKINIT + char **cert_hash; +#endif /* APPLE_PKINIT */ + 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; +#if APPLE_PKINIT + *cert_hash = NULL; +#endif /* APPLE_PKINIT */ + 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 APPLE_PKINIT + if (strlen(argv[i]) == 9 && + !strcmp("-certhash", argv[i])) { + if (++i > argc - 2) + return -1; + else { + *cert_hash = argv[i]; + continue; + } + } +#endif /* APPLE_PKINIT */ + 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" +#if APPLE_PKINIT + "\t\t[-certhash hash_string]\n" +#endif /* APPLE_PKINIT */ + ); + 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" + "\t\tok_as_delegate\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" + "\t\tok_as_delegate\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; + char newpw[1024], dummybuf[256]; + static char prompt1[1024], prompt2[1024]; +#if APPLE_PKINIT + char *cert_hash = NULL; +#endif /* APPLE_PKINIT */ + + /* + * We begin with a bad password and DISALLOW_ALL_TIX. The bad + * password must try to pass any password policy in place, and + * must be valid UTF-8 for the arcfour string-to-key). + */ + strcpy(dummybuf, "6F a["); + for (i = strlen(dummybuf); i < sizeof(dummybuf) - 1; i++) + dummybuf[i] = 'a' + (random() % 25); + dummybuf[sizeof(dummybuf) - 1] = '\0'; + + /* 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, +#if APPLE_PKINIT + &cert_hash, +#endif /* APPLE_PKINIT */ + "add_principal")) { + kadmin_addprinc_usage("add_principal"); + kadmin_free_tl_data(&princ); /* need to free ks_tuple also??? */ + return; + } + +#if APPLE_PKINIT + if(cert_hash != NULL) { + fprintf(stderr, + "add_principal: -certhash not allowed; use modify_principal\n"); + return; + } +#endif /* APPLE_PKINIT */ + + 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; + + snprintf(prompt1, sizeof(prompt1), + "Enter password for principal \"%.900s\"", + canon); + snprintf(prompt2, sizeof(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 APPLE_PKINIT + char *cert_hash = NULL; +#endif /* APPLE_PKINIT */ + + 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); + if (retval) { + com_err("modify_principal", retval, "while getting \"%s\".", + canon); + krb5_free_principal(context, kprinc); + 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, +#if APPLE_PKINIT + &cert_hash, +#endif /* APPLE_PKINIT */ + "modify_principal"); + if (ks_tuple != NULL) { + free(ks_tuple); + kadmin_modprinc_usage("modify_principal"); + free(canon); + krb5_free_principal(context, kprinc); + kadmin_free_tl_data(&princ); /* Apple had this commented out. Why? */ + return; + } + if (retval) { + kadmin_modprinc_usage("modify_principal"); + free(canon); + krb5_free_principal(context, kprinc); + kadmin_free_tl_data(&princ); /* Apple had this commented out. Why? */ + return; + } + if (randkey) { + fprintf(stderr, "modify_principal: -randkey not allowed\n"); + krb5_free_principal(context, princ.principal); + free(canon); + krb5_free_principal(context, kprinc); + 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); + krb5_free_principal(context, kprinc); + kadmin_free_tl_data(&princ); + return; + } +#if APPLE_PKINIT + if (cert_hash) { + /* + * Use something other than the 1st preferred enctype here for fallback + * to pwd authentication + */ + krb5_key_salt_tuple key_salt = {ENCTYPE_ARCFOUR_HMAC, KRB5_KDB_SALTTYPE_CERTHASH}; + krb5_keyblock keyblock; + kadm5_ret_t kadmin_rtn; + + keyblock.magic = KV5M_KEYBLOCK; + keyblock.enctype = ENCTYPE_ARCFOUR_HMAC; + keyblock.length = strlen(cert_hash); + keyblock.contents = (krb5_octet *)cert_hash; + kadmin_rtn = kadm5_setkey_principal_3(handle, kprinc, + TRUE, /* keepold - we're appending */ + 1, &key_salt, + &keyblock, 1); + if (kadmin_rtn) { + com_err("modify_principal", kadmin_rtn, + "while adding certhash for \"%s\".", canon); + printf("realm %s data %s\n", (char *)kprinc->realm.data, (char *)kprinc->data->data); + free(canon); + krb5_free_principal(context, princ.principal); + krb5_free_principal(context, kprinc); + return; + } + retval = 0; + } +#endif /* APPLE_PKINIT */ + if (mask) { + /* skip this if all we're doing is setting certhash */ + retval = kadm5_modify_principal(handle, &princ, mask); + } + krb5_free_principal(context, kprinc); + 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; + } + free(canon); + canon = NULL; + retval = krb5_unparse_name(context, dprinc.principal, &canon); + if (retval) { + com_err("get_principal", retval, "while canonicalizing principal"); + kadm5_free_principal_ent(handle, &dprinc); + 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))) + snprintf(enctype, sizeof(enctype), "", + 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))) + snprintf(salttype, sizeof(salttype), "", + key_data->key_data_type[1]); + printf("%s\n", salttype); + } else + printf("no salt\n"); + } + printf("MKey: vno %d\n", + dprinc.mkvno); + + 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-7/src/kadmin/cli/kadmin.h b/krb5-1-7/src/kadmin/cli/kadmin.h new file mode 100644 index 000000000..745ebcb2b --- /dev/null +++ b/krb5-1-7/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 +#include +#else +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#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-7/src/kadmin/cli/kadmin.local.M b/krb5-1-7/src/kadmin/cli/kadmin.local.M new file mode 100644 index 000000000..00df30db6 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/kadmin.local.M @@ -0,0 +1 @@ +.so man1/kadmin.1 diff --git a/krb5-1-7/src/kadmin/cli/kadmin_ct.ct b/krb5-1-7/src/kadmin/cli/kadmin_ct.ct new file mode 100644 index 000000000..05a4efb84 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/cli/keytab.c b/krb5-1-7/src/kadmin/cli/keytab.c new file mode 100644 index 000000000..89fbe66b1 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/keytab.c @@ -0,0 +1,490 @@ +/* + * 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 +#include +#include +#include + +#include "k5-int.h" +#include +#include +#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; + +#ifdef KADMIN_LOCAL +static int norandkey; +#endif + +static void add_usage() +{ +#ifdef KADMIN_LOCAL + fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] [principal | -glob princ-exp] [...]\n"); +#else + fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...]\n"); +#endif +} + +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 { + if (asprintf(keytab_str, "WRFILE:%s", *keytab_str) < 0) { + *keytab_str = NULL; + com_err(whoami, ENOMEM, "while creating keytab name"); + return 1; + } + } + + 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; +#ifdef KADMIN_LOCAL + norandkey = 0; +#endif + 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++; +#ifdef KADMIN_LOCAL + } else if (strcmp(*argv, "-norandkey") == 0) { + norandkey++; +#endif + } 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; + } + +#ifdef KADMIN_LOCAL + if (norandkey && ks_tuple) { + fprintf(stderr, "cannot specify keysaltlist when not changing key\n"); + return; + } +#endif + + 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; + } + +#ifdef KADMIN_LOCAL + if (norandkey) + code = kadm5_get_principal_keys(handle, princ, &keys, &nkeys); + else +#endif + 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)))) + snprintf(buf, sizeof(buf), "etype %d", enctype); + + return buf; +} diff --git a/krb5-1-7/src/kadmin/cli/keytab_local.c b/krb5-1-7/src/kadmin/cli/keytab_local.c new file mode 100644 index 000000000..1f029a7a9 --- /dev/null +++ b/krb5-1-7/src/kadmin/cli/keytab_local.c @@ -0,0 +1,9 @@ +/* + * A wrapper around keytab.c used by kadmin.local to expose the -norandkey + * flag. This avoids building two object files from the same source file, + * which is otherwise tricky with compilers that don't support -c and -o + * at the same time. + */ + +#define KADMIN_LOCAL +#include "keytab.c" diff --git a/krb5-1-7/src/kadmin/cli/ss_wrapper.c b/krb5-1-7/src/kadmin/cli/ss_wrapper.c new file mode 100644 index 000000000..f73ba8238 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#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-7/src/kadmin/cli/strftime.c b/krb5-1-7/src/kadmin/cli/strftime.c new file mode 100644 index 000000000..6fb621e41 --- /dev/null +++ b/krb5-1-7/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 +#include + +/* 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-7/src/kadmin/dbutil/Makefile.in b/krb5-1-7/src/kadmin/dbutil/Makefile.in new file mode 100644 index 000000000..e88d8b323 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/Makefile.in @@ -0,0 +1,36 @@ +thisconfigdir=../.. +myfulldir=kadmin/dbutil +mydir=kadmin/dbutil +BUILDTOP=$(REL)..$(S).. +DEFS= +LOCALINCLUDES = -I. +PROG_LIBPATH=-L$(TOPLIBD) $(KRB5_LIBPATH) +PROG_RPATH=$(KRB5_LIBDIR) +KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) + +PROG = kdb5_util + +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 kdb5_mkey.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 kdb5_mkey.o + +GETDATE = ../cli/getdate.o + +all:: $(PROG) + +$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(GETDATE) + $(CC_LINK) -o $(PROG) $(OBJS) $(GETDATE) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_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 + diff --git a/krb5-1-7/src/kadmin/dbutil/deps b/krb5-1-7/src/kadmin/dbutil/deps new file mode 100644 index 000000000..fadc1992c --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/deps @@ -0,0 +1,168 @@ +# +# Generated makefile dependencies follow. +# +$(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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_log.h $(SRCTOP)/include/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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_log.h $(SRCTOP)/include/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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 +$(OUTPRE)kdb5_mkey.$(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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_log.h $(SRCTOP)/include/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_mkey.c kdb5_util.h diff --git a/krb5-1-7/src/kadmin/dbutil/dump.c b/krb5-1-7/src/kadmin/dbutil/dump.c new file mode 100644 index 000000000..55677f7a5 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/dump.c @@ -0,0 +1,2590 @@ +/* + * kadmin/dbutil/dump.c + * + * Copyright 1990,1991,2001,2006,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include +#include "kdb5_util.h" +#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) +#include +#endif /* HAVE_REGEX_H */ + +/* + * Needed for master key conversion. + */ +static int mkey_convert; +krb5_keyblock new_master_keyblock; +krb5_kvno new_mkvno; + +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 +#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 iprop_version = { + "Kerberos iprop version", + "iprop", + 0, + 0, + dump_k5beta7_princ_withpolicy, + 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; +extern krb5_db_entry master_entry; + +/* 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 ipropoption[] = "-i"; +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... + */ +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; + krb5_kvno kvno; + + is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ); + + if (is_mkey) { + retval = add_new_mkey(context, db_entry, &new_master_keyblock, new_mkvno); + if (retval) + return retval; + } else { + for (i=0; i < db_entry->n_key_data; i++) { + krb5_keyblock *tmp_mkey; + + key_data = &db_entry->key_data[i]; + if (key_data->key_data_length == 0) + continue; + retval = krb5_dbe_find_mkey(context, master_keylist, db_entry, &tmp_mkey); + if (retval) + return retval; + retval = krb5_dbekd_decrypt_key_data(context, tmp_mkey, + key_data, &v5plainkey, + &keysalt); + if (retval) + return retval; + + memset(&new_key_data, 0, sizeof(new_key_data)); + + key_ptr = &v5plainkey; + kvno = (krb5_kvno) key_data->key_data_kvno; + + retval = krb5_dbekd_encrypt_key_data(context, &new_master_keyblock, + key_ptr, &keysalt, + (int) 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; + } + assert(new_mkvno > 0); + retval = krb5_dbe_update_mkvno(context, db_entry, new_mkvno); + if (retval) + return retval; + } + 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 (asprintf(&file_ok, "%s%s", file_name, ok) < 0) { + com_err(progname, ENOMEM, + "while allocating filename for update_ok_file"); + exit_status++; + return; + } + 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; innames; 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; in_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); + free(mod_name); + free(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); + free(mod_name); + free(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, "%lu\t%lu\t%d\t%d\t%d\t%d\t%s\t%d\t", + (unsigned long) strlen(name), + (unsigned long) 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; ikey_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; ikey_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; ikey_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; ikey_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); + free(mod_name); + } + free(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 ] + * n_key_data*[ver kvno ver*(type length )] + * + * 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%lu\t%d\t%d\t%d\t%s\t", + (int) entry->len, + (unsigned long) 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; itl_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; countern_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; ikey_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; jkey_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; ie_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; + } + } + free(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. + * 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 *ofile; + krb5_error_code kret, retval; + dump_version *dump; + int aindex; + krb5_boolean locked; + char *new_mkey_file = 0; + bool_t dump_sno = FALSE; + kdb_log_context *log_ctx; + char **db_args = 0; /* XXX */ + + /* + * Parse the arguments. + */ + ofile = (char *) NULL; + dump = &r1_3_version; + arglist.verbose = 0; + new_mkey_file = 0; + mkey_convert = 0; + backwards = 0; + recursive = 0; + log_ctx = util_context->kdblog_context; + + /* + * 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], ipropoption)) { + if (log_ctx && log_ctx->iproprole) { + dump = &iprop_version; + /* + * dump_sno is used to indicate if the serial + * # should be populated in the output + * file to be used later by iprop for updating + * the slave's update log when loading + */ + dump_sno = TRUE; + } else { + fprintf(stderr, _("Iprop not enabled\n")); + exit_status++; + return; + } + } 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(progname, 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, + NULL, NULL, + &master_keyblock); + if (retval) { + com_err(progname, retval, + "while reading master key"); + exit(1); + } + retval = krb5_db_verify_master_key(util_context, + master_princ, + IGNORE_VNO, + &master_keyblock); + if (retval) { + com_err(progname, 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) { + krb5_kvno kt_kvno; + + if (global_params.mask & KADM5_CONFIG_KVNO) + kt_kvno = global_params.kvno; + else + kt_kvno = IGNORE_VNO; + + if ((retval = krb5_db_fetch_mkey(util_context, master_princ, + new_master_keyblock.enctype, + FALSE, + FALSE, + new_mkey_file, + &kt_kvno, + NULL, + &new_master_keyblock))) { + com_err(progname, retval, "while reading new master key"); + exit(1); + } + } else { + printf("Please enter new master key....\n"); + if ((retval = krb5_db_fetch_mkey(util_context, master_princ, + new_master_keyblock.enctype, + TRUE, + TRUE, + NULL, NULL, NULL, + &new_master_keyblock))) { + com_err(progname, retval, "while reading new master key"); + exit(1); + } + } + /* + * get new master key vno that will be used to protect princs, used + * later on. + */ + new_mkvno = get_next_kvno(util_context, &master_entry); + } + + 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, + progname, ofile, error_message(errno)); + exit_status++; + return; + } + if ((kret = krb5_lock_file(util_context, + fileno(f), + KRB5_LOCKMODE_EXCLUSIVE))) { + fprintf(stderr, oflock_error, + progname, ofile, error_message(kret)); + exit_status++; + } + else + locked = 1; + } else { + f = stdout; + } + if (f && !(kret)) { + arglist.programname = progname; + arglist.ofile = f; + arglist.kcontext = util_context; + fprintf(arglist.ofile, "%s", dump->header); + + if (dump_sno) { + if (ulog_map(util_context, global_params.iprop_logfile, + global_params.iprop_ulogsize, FKCOMMAND, db_args)) { + fprintf(stderr, + _("%s: Could not map log\n"), progname); + exit_status++; + goto unlock_and_return; + } + + /* + * We grab the lock twice (once again in the iterator call), + * but that's ok since the lock func handles incr locks held. + */ + if (krb5_db_lock(util_context, KRB5_LOCKMODE_SHARED)) { + fprintf(stderr, + _("%s: Couldn't grab lock\n"), progname); + exit_status++; + goto unlock_and_return; + } + + fprintf(f, " %u", log_ctx->ulog->kdb_last_sno); + fprintf(f, " %u", log_ctx->ulog->kdb_last_time.seconds); + fprintf(f, " %u", log_ctx->ulog->kdb_last_time.useconds); + } + + 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, + progname, dump->name, error_message(kret)); + exit_status++; + if (dump_sno) + (void) krb5_db_unlock(util_context); + } + if (dump->dump_policy && + (kret = krb5_db_iter_policy( util_context, "*", dump->dump_policy, + &arglist))) { + fprintf(stderr, dumprec_err, progname, 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); + } + } +unlock_and_return: + 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; itl_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; itl_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 && (ikey_data_ver = (krb5_int16) t1; + kdatap->key_data_kvno = (krb5_int16) t2; + + for (j=0; jkey_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) + char *fname; + krb5_context kcontext; + FILE *filep; + int verbose; + int *linenop; +{ + 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 *dumpfile; + char *dbname; + char *dbname_tmp; + char buf[BUFSIZ]; + dump_version *load; + int update, verbose; + krb5_int32 crflags; + int aindex; + int db_locked = 0; + char iheader[MAX_HEADER]; + kdb_log_context *log_ctx; + int add_update = 1; + uint32_t caller, last_sno, last_seconds, last_useconds; + + /* + * Parse the arguments. + */ + 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; + log_ctx = util_context->kdblog_context; + + 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], ipropoption)) { + if (log_ctx && log_ctx->iproprole) { + load = &iprop_version; + add_update = FALSE; + } else { + fprintf(stderr, _("Iprop not enabled\n")); + exit_status++; + return; + } + } 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 (asprintf(&dbname_tmp, "%s%s", dbname, dump_tmptrail) < 0) { + fprintf(stderr, no_name_mem_fmt, progname); + exit_status++; + return; + } + + /* + * Initialize the Kerberos context and error tables. + */ + if ((kret = kadm5_init_krb5_context(&kcontext))) { + fprintf(stderr, ctx_err_fmt, progname); + 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", progname); + free(dbname_tmp); + exit_status++; + return; + } + + if (log_ctx && log_ctx->iproprole) + kcontext->kdblog_context = log_ctx; + + /* + * Open the dumpfile + */ + if (dumpfile) { + if ((f = fopen(dumpfile, "r")) == NULL) { + fprintf(stderr, dfile_err_fmt, progname, 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", progname, + 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, progname, 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, progname, 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", progname, 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(progname, 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", progname, emsg); + krb5_free_error_message (kcontext, emsg); + } else { + fprintf(stderr, dbcreaterr_fmt, + progname, 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", progname, emsg); + krb5_free_error_message (kcontext, emsg); + } else { + fprintf(stderr, dbinit_err_fmt, + progname, 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", + progname, error_message(kret)); + exit_status++; + goto error; + } + } + else + db_locked = 1; + + if (log_ctx && log_ctx->iproprole) { + if (add_update) + caller = FKCOMMAND; + else + caller = FKPROPD; + + if (ulog_map(kcontext, global_params.iprop_logfile, + global_params.iprop_ulogsize, caller, db5util_db_args)) { + fprintf(stderr, _("%s: Could not map log\n"), + progname); + exit_status++; + goto error; + } + + /* + * We don't want to take out the ulog out from underneath + * kadmind so we reinit the header log. + * + * We also don't want to add to the update log since we + * are doing a whole sale replace of the db, because: + * we could easily exceed # of update entries + * we could implicity delete db entries during a replace + * no advantage in incr updates when entire db is replaced + */ + if (!update) { + memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); + + log_ctx->ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + log_ctx->ulog->db_version_num = KDB_VERSION; + log_ctx->ulog->kdb_state = KDB_STABLE; + log_ctx->ulog->kdb_block = ULOG_BLOCK; + + log_ctx->iproprole = IPROP_NULL; + + if (!add_update) { + sscanf(buf, "%s %u %u %u", iheader, &last_sno, + &last_seconds, &last_useconds); + + log_ctx->ulog->kdb_last_sno = last_sno; + log_ctx->ulog->kdb_last_time.seconds = + last_seconds; + log_ctx->ulog->kdb_last_time.useconds = + last_useconds; + } + } + } + + if (restore_dump(progname, kcontext, (dumpfile) ? dumpfile : stdin_name, + f, verbose, load)) { + fprintf(stderr, restfail_fmt, + progname, 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, + progname, dbname, error_message(kret)); + exit_status++; + } + +#if 0 + if ((kret = krb5_db_fini(kcontext))) { + fprintf(stderr, close_err_fmt, + progname, 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", + progname, 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, + progname, 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-7/src/kadmin/dbutil/import_err.et b/krb5-1-7/src/kadmin/dbutil/import_err.et new file mode 100644 index 000000000..48bb8fb9a --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/import_err.et @@ -0,0 +1,22 @@ +error_table imp +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_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 ?" +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_GET_PARAMS, "while retrieving configuration parameters" +end diff --git a/krb5-1-7/src/kadmin/dbutil/kadm5_create.c b/krb5-1-7/src/kadmin/dbutil/kadm5_create.c new file mode 100644 index 000000000..894edf364 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kadm5_create.c @@ -0,0 +1,331 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "fake-addrinfo.h" + + +#include +#include +#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; + + asprintf(&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 + * (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 = 0, *p; + 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; + } + for (p = ai->ai_canonname; *p; p++) { +#ifdef isascii + if (!isascii(*p)) + continue; +#else + if (*p < ' ') + continue; + if (*p > '~') + continue; +#endif + if (!isupper(*p)) + continue; + *p = tolower(*p); + } + if (asprintf(&service_name, "kadmin/%s", ai->ai_canonname) < 0) { + ret = ENOMEM; + fprintf(stderr, "Out of memory\n"); + freeaddrinfo(ai); + goto clean_and_exit; + } + 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: + free(service_name); + + 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-7/src/kadmin/dbutil/kdb5_create.c b/krb5-1-7/src/kadmin/dbutil/kdb5_create.c new file mode 100644 index 000000000..d4a082c77 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_create.c @@ -0,0 +1,513 @@ +/* + * kadmin/dbutil/kdb5_create.c + * + * Copyright 1990,1991,2001, 2002, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include +#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; + kdb_log_context *log_ctx; + krb5_kvno mkey_kvno; + int strong_random = 1; + + while ((optchar = getopt(argc, argv, "sW")) != -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 'W': + strong_random = 0; + 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; + + log_ctx = util_context->kdblog_context; + + printf ("Loading random data\n"); + retval = krb5_c_random_os_entropy (util_context, strong_random, NULL); + if (retval) { + com_err (progname, 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(progname, 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); + if (pw_str == NULL) { + com_err(progname, ENOMEM, "while creating new master key"); + exit_status++; return; + } + + retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, + pw_str, &pw_size); + if (retval) { + com_err(progname, 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(progname, 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(progname, 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(progname, retval, "while initializing random key generator"); + exit_status++; return; + } + if ((retval = krb5_db_create(util_context, + db5util_db_args))) { + com_err(progname, retval, "while creating database '%s'", + global_params.dbname); + exit_status++; return; + } +/* if ((retval = krb5_db_fini(util_context))) { */ +/* com_err(progname, retval, "while closing current database"); */ +/* exit_status++; return; */ +/* } */ +/* if ((retval = krb5_db_open(util_context, db5util_db_args, KRB5_KDB_OPEN_RW))) { */ +/* com_err(progname, retval, "while initializing the database '%s'", */ +/* global_params.dbname); */ +/* exit_status++; return; */ +/* } */ + + if (log_ctx && log_ctx->iproprole) { + if ((retval = ulog_map(util_context, global_params.iprop_logfile, + global_params.iprop_ulogsize, FKCOMMAND, + db5util_db_args))) { + com_err(argv[0], retval, + _("while creating update log")); + exit_status++; + return; + } + + /* + * We're reinitializing the update log in case one already + * existed, but this should never happen. + */ + (void) memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); + + log_ctx->ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + log_ctx->ulog->db_version_num = KDB_VERSION; + log_ctx->ulog->kdb_state = KDB_STABLE; + log_ctx->ulog->kdb_block = ULOG_BLOCK; + + /* + * Since we're creating a new db we shouldn't worry about + * adding the initial principals since any slave might as well + * do full resyncs from this newly created db. + */ + log_ctx->iproprole = IPROP_NULL; + } + + 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(progname, 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. + */ + + /* + * Determine the kvno to use, it must be that used to create the master key + * princ. + */ + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + + retval = krb5_db_store_master_key(util_context, + global_params.stash_file, + master_princ, + mkey_kvno, + &master_keyblock, + mkey_password); + if (retval) { + com_err(progname, 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_kvno mkey_kvno; + krb5_timestamp now; + struct iterate_args iargs; + int nentries = 1; + krb5_actkvno_node actkvno; + + 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; + + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key, + &master_keyblock, NULL, + mkey_kvno, entry.key_data))) + return retval; + /* + * There should always be at least one "active" mkey so creating the + * KRB5_TL_ACTKVNO entry now so the initial mkey is active. + */ + actkvno.next = NULL; + actkvno.act_kvno = mkey_kvno; + /* earliest possible time in case system clock is set back */ + actkvno.act_time = 0; + if ((retval = krb5_dbe_update_actkvno(context, &entry, &actkvno))) + return retval; + + /* so getprinc shows the right kvno */ + if ((retval = krb5_dbe_update_mkvno(context, &entry, mkey_kvno))) + 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-7/src/kadmin/dbutil/kdb5_destroy.c b/krb5-1-7/src/kadmin/dbutil/kdb5_destroy.c new file mode 100644 index 000000000..9640286ae --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_destroy.c @@ -0,0 +1,113 @@ +/* + * admin/destroy/kdb5_destroy.c + * + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include "com_err.h" +#include +#include +#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(progname, retval1, "while initializing krb5_context"); + exit(1); + } + + if ((retval1 = krb5_set_default_realm(context, + util_context->default_realm))) { + com_err(progname, retval1, "while setting default realm name"); + exit(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(progname, retval1, "deleting database '%s'",dbname); + exit_status++; return; + } + + if (global_params.iprop_enabled) { + (void) unlink(global_params.iprop_logfile); + } + + dbactive = FALSE; + printf("** Database '%s' destroyed.\n", dbname); + return; +} diff --git a/krb5-1-7/src/kadmin/dbutil/kdb5_mkey.c b/krb5-1-7/src/kadmin/dbutil/kdb5_mkey.c new file mode 100644 index 000000000..4916de2cb --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_mkey.c @@ -0,0 +1,1447 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "kdb5_util.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 +#ifdef SOLARIS_REGEXPS +#include +#endif +#ifdef POSIX_REGEXPS +#include +#endif + +extern krb5_keyblock master_keyblock; /* current mkey */ +extern krb5_kvno master_kvno; +extern krb5_principal master_princ; +extern krb5_keylist_node *master_keylist; +extern krb5_data master_salt; +extern char *mkey_password; +extern char *progname; +extern int exit_status; +extern kadm5_config_params global_params; +extern krb5_context util_context; +extern time_t get_date(char *); + +static char *strdate(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; +} + +krb5_kvno +get_next_kvno(krb5_context context, krb5_db_entry *entry) +{ + krb5_kvno new_kvno; + + new_kvno = krb5_db_get_key_data_kvno(context, entry->n_key_data, + entry->key_data); + new_kvno++; + /* deal with wrapping */ + if (new_kvno == 0) + new_kvno = 1; /* knvo must not be 0 as this is special value (IGNORE_VNO) */ + + return (new_kvno); +} + +krb5_error_code +add_new_mkey(krb5_context context, krb5_db_entry *master_entry, + krb5_keyblock *new_mkey, krb5_kvno use_mkvno) +{ + krb5_error_code retval = 0; + int old_key_data_count, i; + krb5_kvno new_mkey_kvno; + krb5_key_data tmp_key_data, *old_key_data; + krb5_mkey_aux_node *mkey_aux_data_head = NULL, **mkey_aux_data; + krb5_keylist_node *keylist_node; + + /* do this before modifying master_entry key_data */ + new_mkey_kvno = get_next_kvno(context, master_entry); + /* verify the requested mkvno if not 0 is the one that would be used here. */ + if (use_mkvno != 0 && new_mkey_kvno != use_mkvno) + return (KRB5_KDB_KVNONOMATCH); + + /* save the old keydata */ + old_key_data_count = master_entry->n_key_data; + old_key_data = master_entry->key_data; + + /* alloc enough space to hold new and existing key_data */ + /* + * The encrypted key is malloc'ed by krb5_dbekd_encrypt_key_data and + * krb5_key_data key_data_contents is a pointer to this key. Using some + * logic from master_key_convert(). + */ + master_entry->key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) * + (old_key_data_count + 1)); + if (master_entry->key_data == NULL) + return (ENOMEM); + + memset((char *) master_entry->key_data, 0, + sizeof(krb5_key_data) * (old_key_data_count + 1)); + master_entry->n_key_data = old_key_data_count + 1; + + /* Note, mkey does not have salt */ + /* add new mkey encrypted with itself to mkey princ entry */ + if ((retval = krb5_dbekd_encrypt_key_data(context, new_mkey, + new_mkey, NULL, + (int) new_mkey_kvno, + &master_entry->key_data[0]))) { + return (retval); + } + /* the mvkno should be that of the newest mkey */ + if ((retval = krb5_dbe_update_mkvno(context, master_entry, new_mkey_kvno))) { + krb5_free_key_data_contents(context, &master_entry->key_data[0]); + return (retval); + } + /* + * Need to decrypt old keys with the current mkey which is in the global + * master_keyblock and encrypt those keys with the latest mkey. And while + * the old keys are being decrypted, use those to create the + * KRB5_TL_MKEY_AUX entries which store the latest mkey encrypted by one of + * the older mkeys. + * + * The new mkey is followed by existing keys. + * + * First, set up for creating a krb5_mkey_aux_node list which will be used + * to update the mkey aux data for the mkey princ entry. + */ + mkey_aux_data_head = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (mkey_aux_data_head == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(mkey_aux_data_head, 0, sizeof(krb5_mkey_aux_node)); + mkey_aux_data = &mkey_aux_data_head; + + for (keylist_node = master_keylist, i = 1; keylist_node != NULL; + keylist_node = keylist_node->next, i++) { + + /* + * Create a list of krb5_mkey_aux_node nodes. One node contains the new + * mkey encrypted by an old mkey and the old mkey's kvno (one node per + * old mkey). + */ + if (*mkey_aux_data == NULL) { + /* *mkey_aux_data points to next field of previous node */ + *mkey_aux_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (*mkey_aux_data == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(*mkey_aux_data, 0, sizeof(krb5_mkey_aux_node)); + } + + memset(&tmp_key_data, 0, sizeof(tmp_key_data)); + /* encrypt the new mkey with the older mkey */ + retval = krb5_dbekd_encrypt_key_data(context, &keylist_node->keyblock, + new_mkey, + NULL, /* no keysalt */ + (int) new_mkey_kvno, + &tmp_key_data); + if (retval) + goto clean_n_exit; + + (*mkey_aux_data)->latest_mkey = tmp_key_data; + (*mkey_aux_data)->mkey_kvno = keylist_node->kvno; + mkey_aux_data = &((*mkey_aux_data)->next); + + /* + * Store old key in master_entry keydata past the new mkey + */ + retval = krb5_dbekd_encrypt_key_data(context, new_mkey, + &keylist_node->keyblock, + NULL, /* no keysalt */ + (int) keylist_node->kvno, + &master_entry->key_data[i]); + if (retval) + goto clean_n_exit; + } + assert(i == old_key_data_count + 1); + + if ((retval = krb5_dbe_update_mkey_aux(context, master_entry, + mkey_aux_data_head))) { + goto clean_n_exit; + } + master_entry->mask |= KADM5_KEY_DATA; + +clean_n_exit: + krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_head); + return (retval); +} + +void +kdb5_add_mkey(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, nentries = 0; + krb5_boolean more = 0; + krb5_data pwd; + krb5_kvno new_mkey_kvno; + krb5_keyblock new_mkeyblock; + krb5_enctype new_master_enctype = ENCTYPE_UNKNOWN; + char *new_mkey_password; + krb5_db_entry master_entry; + krb5_timestamp now; + + /* + * The command table entry for this command causes open_db_and_mkey() to be + * called first to open the KDB and get the current mkey. + */ + + memset(&new_mkeyblock, 0, sizeof(new_mkeyblock)); + memset(&master_princ, 0, sizeof(master_princ)); + master_salt.data = NULL; + + while ((optchar = getopt(argc, argv, "e:s")) != -1) { + switch(optchar) { + case 'e': + if (krb5_string_to_enctype(optarg, &new_master_enctype)) { + com_err(progname, EINVAL, "%s is an invalid enctype", optarg); + exit_status++; + return; + } + break; + case 's': + do_stash++; + break; + case '?': + default: + usage(); + return; + } + } + + if (new_master_enctype == ENCTYPE_UNKNOWN) + new_master_enctype = global_params.enctype; + + /* 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(progname, retval, "while setting up master key name"); + exit_status++; + return; + } + + retval = krb5_db_get_principal(util_context, master_princ, &master_entry, + &nentries, &more); + if (retval != 0) { + com_err(progname, retval, + "while getting master key principal %s", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries == 0) { + com_err(progname, KRB5_KDB_NOENTRY, + "principal %s not found in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries > 1) { + com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, + "principal %s has multiple entries in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + printf("Creating new master key for master key principal '%s'\n", + mkey_fullname); + + printf("You will be prompted for a new 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); + if (pw_str == NULL) { + com_err(progname, ENOMEM, "while creating new master key"); + exit_status++; + goto cleanup_return; + } + + retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, + pw_str, &pw_size); + if (retval) { + com_err(progname, retval, "while reading new master key from keyboard"); + exit_status++; + goto cleanup_return; + } + new_mkey_password = pw_str; + + pwd.data = new_mkey_password; + pwd.length = strlen(new_mkey_password); + retval = krb5_principal2salt(util_context, master_princ, &master_salt); + if (retval) { + com_err(progname, retval, "while calculating master key salt"); + exit_status++; + goto cleanup_return; + } + + retval = krb5_c_string_to_key(util_context, new_master_enctype, + &pwd, &master_salt, &new_mkeyblock); + if (retval) { + com_err(progname, retval, "while transforming master key from password"); + exit_status++; + goto cleanup_return; + } + + retval = add_new_mkey(util_context, &master_entry, &new_mkeyblock, 0); + if (retval) { + com_err(progname, retval, "adding new master key to master principal"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, "while getting current time"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, &master_entry, + now, master_princ))) { + com_err(progname, retval, "while updating the master key principal modification time"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_db_put_principal(util_context, &master_entry, &nentries))) { + (void) krb5_db_fini(util_context); + com_err(progname, retval, "while adding master key entry to the database"); + exit_status++; + goto cleanup_return; + } + + if (do_stash) { + retval = krb5_db_store_master_key(util_context, + global_params.stash_file, + master_princ, + new_mkey_kvno, + &new_mkeyblock, + mkey_password); + if (retval) { + com_err(progname, errno, "while storing key"); + printf("Warning: couldn't stash master key.\n"); + } + } + +cleanup_return: + /* clean up */ + (void) krb5_db_fini(util_context); + zap((char *)master_keyblock.contents, master_keyblock.length); + free(master_keyblock.contents); + zap((char *)new_mkeyblock.contents, new_mkeyblock.length); + free(new_mkeyblock.contents); + if (pw_str) { + zap(pw_str, pw_size); + free(pw_str); + } + free(master_salt.data); + krb5_free_unparsed_name(util_context, mkey_fullname); + return; +} + +void +kdb5_use_mkey(int argc, char *argv[]) +{ + krb5_error_code retval; + char *mkey_fullname = NULL; + krb5_kvno use_kvno; + krb5_timestamp now, start_time; + krb5_actkvno_node *actkvno_list = NULL, *new_actkvno = NULL, + *prev_actkvno, *cur_actkvno; + krb5_db_entry master_entry; + int nentries = 0; + krb5_boolean more = FALSE; + krb5_keylist_node *keylist_node; + krb5_boolean inserted = FALSE; + + memset(&master_princ, 0, sizeof(master_princ)); + + if (argc < 2 || argc > 3) { + /* usage calls exit */ + usage(); + } + + use_kvno = atoi(argv[1]); + if (use_kvno == 0) { + com_err(progname, EINVAL, "0 is an invalid KVNO value"); + exit_status++; + return; + } else { + /* verify use_kvno is valid */ + for (keylist_node = master_keylist; keylist_node != NULL; + keylist_node = keylist_node->next) { + if (use_kvno == keylist_node->kvno) + break; + } + if (!keylist_node) { + com_err(progname, EINVAL, "%d is an invalid KVNO value", use_kvno); + exit_status++; + return; + } + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, "while getting current time"); + exit_status++; + return; + } + + if (argc == 3) { + time_t t = get_date(argv[2]); + if (t == -1) { + com_err(progname, 0, "could not parse date-time string '%s'", + argv[2]); + exit_status++; + return; + } else + start_time = (krb5_timestamp) t; + } else { + start_time = now; + } + + /* + * Need to: + * + * 1. get mkey princ + * 2. get krb5_actkvno_node list + * 3. add use_kvno to actkvno list (sorted in right spot) + * 4. update mkey princ's tl data + * 5. put mkey princ. + */ + + /* 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(progname, retval, "while setting up master key name"); + exit_status++; + goto cleanup_return; + } + + retval = krb5_db_get_principal(util_context, master_princ, &master_entry, + &nentries, &more); + if (retval != 0) { + com_err(progname, retval, + "while getting master key principal %s", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries == 0) { + com_err(progname, KRB5_KDB_NOENTRY, + "principal %s not found in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries > 1) { + com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, + "principal %s has multiple entries in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, + "while looking up active version of master key"); + exit_status++; + goto cleanup_return; + } + + /* + * If an entry already exists with the same kvno either delete it or if it's + * the only entry, just set its active time. + */ + for (prev_actkvno = NULL, cur_actkvno = actkvno_list; + cur_actkvno != NULL; + prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { + + if (cur_actkvno->act_kvno == use_kvno) { + /* delete it */ + if (prev_actkvno) { + prev_actkvno->next = cur_actkvno->next; + cur_actkvno->next = NULL; + krb5_dbe_free_actkvno_list(util_context, cur_actkvno); + } else { + if (cur_actkvno->next) { + /* delete it from front of list */ + actkvno_list = cur_actkvno->next; + cur_actkvno->next = NULL; + krb5_dbe_free_actkvno_list(util_context, cur_actkvno); + } else { + /* There's only one entry, go ahead and change the time */ + cur_actkvno->act_time = start_time; + inserted = TRUE; + } + } + break; + } + } + + if (!inserted) { + /* alloc enough space to hold new and existing key_data */ + new_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node)); + if (new_actkvno == NULL) { + com_err(progname, ENOMEM, "while adding new master key"); + exit_status++; + goto cleanup_return; + } + memset(new_actkvno, 0, sizeof(krb5_actkvno_node)); + new_actkvno->act_kvno = use_kvno; + new_actkvno->act_time = start_time; + + /* insert new act kvno node */ + + if (actkvno_list == NULL) { + /* new actkvno is the list */ + actkvno_list = new_actkvno; + } else { + for (prev_actkvno = NULL, cur_actkvno = actkvno_list; + cur_actkvno != NULL; + prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { + + if (new_actkvno->act_time < cur_actkvno->act_time) { + if (prev_actkvno) { + prev_actkvno->next = new_actkvno; + new_actkvno->next = cur_actkvno; + } else { + new_actkvno->next = actkvno_list; + actkvno_list = new_actkvno; + } + break; + } else if (cur_actkvno->next == NULL) { + /* end of line, just add new node to end of list */ + cur_actkvno->next = new_actkvno; + break; + } + } + } + } + + if (actkvno_list->act_time > now) { + com_err(progname, EINVAL, "there must be one master key currently active"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_actkvno(util_context, &master_entry, + actkvno_list))) { + com_err(progname, retval, "while updating actkvno data for master principal entry"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, &master_entry, + now, master_princ))) { + com_err(progname, retval, "while updating the master key principal modification time"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_db_put_principal(util_context, &master_entry, &nentries))) { + (void) krb5_db_fini(util_context); + com_err(progname, retval, "while adding master key entry to the database"); + exit_status++; + goto cleanup_return; + } + +cleanup_return: + /* clean up */ + (void) krb5_db_fini(util_context); + krb5_free_unparsed_name(util_context, mkey_fullname); + krb5_free_principal(util_context, master_princ); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + return; +} + +void +kdb5_list_mkeys(int argc, char *argv[]) +{ + krb5_error_code retval; + char *mkey_fullname = NULL, *output_str = NULL, enctype[BUFSIZ]; + krb5_kvno act_kvno; + krb5_timestamp act_time; + krb5_actkvno_node *actkvno_list = NULL, *cur_actkvno; + krb5_db_entry master_entry; + int nentries = 0; + krb5_boolean more = FALSE; + krb5_keylist_node *cur_kb_node; + krb5_keyblock *act_mkey; + + if (master_keylist == NULL) { + com_err(progname, 0, "master keylist not initialized"); + 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(progname, retval, "while setting up master key name"); + exit_status++; + return; + } + + retval = krb5_db_get_principal(util_context, master_princ, &master_entry, + &nentries, &more); + if (retval != 0) { + com_err(progname, retval, + "while getting master key principal %s", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries == 0) { + com_err(progname, KRB5_KDB_NOENTRY, + "principal %s not found in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries > 1) { + com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, + "principal %s has multiple entries in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, "while looking up active kvno list"); + exit_status++; + goto cleanup_return; + } + + if (actkvno_list == NULL) { + act_kvno = master_entry.key_data[0].key_data_kvno; + } else { + retval = krb5_dbe_find_act_mkey(util_context, master_keylist, + actkvno_list, &act_kvno, &act_mkey); + if (retval == KRB5_KDB_NOACTMASTERKEY) { + /* Maybe we went through a time warp, and the only keys + with activation dates have them set in the future? */ + com_err(progname, retval, ""); + /* Keep going. */ + act_kvno = -1; + } else if (retval != 0) { + com_err(progname, retval, "while looking up active master key"); + exit_status++; + goto cleanup_return; + } + } + + printf("Master keys for Principal: %s\n", mkey_fullname); + + for (cur_kb_node = master_keylist; cur_kb_node != NULL; + cur_kb_node = cur_kb_node->next) { + + if ((retval = krb5_enctype_to_string(cur_kb_node->keyblock.enctype, + enctype, sizeof(enctype)))) { + com_err(progname, retval, "while getting enctype description"); + exit_status++; + goto cleanup_return; + } + + if (actkvno_list != NULL) { + act_time = -1; /* assume actkvno entry not found */ + for (cur_actkvno = actkvno_list; cur_actkvno != NULL; + cur_actkvno = cur_actkvno->next) { + if (cur_actkvno->act_kvno == cur_kb_node->kvno) { + act_time = cur_actkvno->act_time; + break; + } + } + } else { + /* + * mkey princ doesn't have an active knvo list so assume the current + * key is active now + */ + if ((retval = krb5_timeofday(util_context, &act_time))) { + com_err(progname, retval, "while getting current time"); + exit_status++; + goto cleanup_return; + } + } + + if (cur_kb_node->kvno == act_kvno) { + /* * indicates kvno is currently active */ + retval = asprintf(&output_str, "KNVO: %d, Enctype: %s, Active on: %s *\n", + cur_kb_node->kvno, enctype, strdate(act_time)); + } else { + if (act_time != -1) { + retval = asprintf(&output_str, "KNVO: %d, Enctype: %s, Active on: %s\n", + cur_kb_node->kvno, enctype, strdate(act_time)); + } else { + retval = asprintf(&output_str, "KNVO: %d, Enctype: %s, No activate time set\n", + cur_kb_node->kvno, enctype); + } + } + if (retval == -1) { + com_err(progname, ENOMEM, "asprintf could not allocate enough memory to hold output"); + exit_status++; + goto cleanup_return; + } + printf("%s", output_str); + free(output_str); + output_str = NULL; + } + +cleanup_return: + /* clean up */ + (void) krb5_db_fini(util_context); + krb5_free_unparsed_name(util_context, mkey_fullname); + free(output_str); + krb5_free_principal(util_context, master_princ); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + return; +} + +struct update_enc_mkvno { + unsigned int re_match_count; + unsigned int already_current; + unsigned int updated; + unsigned int dry_run : 1; + unsigned int verbose : 1; +#ifdef SOLARIS_REGEXPS + char *expbuf; +#endif +#ifdef POSIX_REGEXPS + regex_t preg; +#endif +#if !defined(SOLARIS_REGEXPS) && !defined(POSIX_REGEXPS) + unsigned char placeholder; +#endif +}; + +/* XXX Duplicated in libkadm5srv! */ +/* + * 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 int 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 ? 3 : 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++ = '$'; + *p++ = '\0'; + return 0; +} + +static int +update_princ_encryption_1(void *cb, krb5_db_entry *ent) +{ + struct update_enc_mkvno *p = cb; + char *pname = 0; + krb5_error_code retval; + int match; + krb5_timestamp now; + int nentries = 1; + int result; + krb5_kvno old_mkvno; + + retval = krb5_unparse_name(util_context, ent->princ, &pname); + if (retval) { + com_err(progname, retval, + "getting string representation of principal name"); + goto fail; + } + + if (krb5_principal_compare(util_context, ent->princ, master_princ)) { + goto skip; + } + +#ifdef SOLARIS_REGEXPS + match = (step(pname, p->expbuf) != 0); +#endif +#ifdef POSIX_REGEXPS + match = (regexec(&p->preg, pname, 0, NULL, 0) == 0); +#endif +#ifdef BSD_REGEXPS + match = (re_exec(pname) != 0); +#endif + if (!match) { + goto skip; + } + p->re_match_count++; + retval = krb5_dbe_lookup_mkvno(util_context, ent, &old_mkvno); + if (retval) { + com_err(progname, retval, + "determining master key used for principal '%s'", + pname); + goto fail; + } + /* Line up "skip" and "update" messages for viewing. */ + if (old_mkvno == new_mkvno) { + if (p->dry_run && p->verbose) + printf("would skip: %s\n", pname); + else if (p->verbose) + printf("skipping: %s\n", pname); + p->already_current++; + goto skip; + } + if (p->dry_run) { + if (p->verbose) + printf("would update: %s\n", pname); + p->updated++; + goto skip; + } else if (p->verbose) + printf("updating: %s\n", pname); + retval = master_key_convert (util_context, ent); + if (retval) { + com_err(progname, retval, + "error re-encrypting key for principal '%s'", pname); + goto fail; + } + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, "while getting current time"); + goto fail; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, ent, + now, master_princ))) { + com_err(progname, retval, + "while updating principal '%s' modification time", pname); + goto fail; + } + + ent->mask |= KADM5_KEY_DATA; + + if ((retval = krb5_db_put_principal(util_context, ent, &nentries))) { + com_err(progname, retval, + "while updating principal '%s' key data in the database", + pname); + goto fail; + } + p->updated++; +skip: + result = 0; + goto egress; +fail: + exit_status++; + result = 1; +egress: + if (pname) + krb5_free_unparsed_name(util_context, pname); + return result; +} + +extern int are_you_sure (const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +int +are_you_sure (const char *format, ...) +{ + va_list va; + char ansbuf[100]; + + va_start(va, format); + vprintf(format, va); + va_end(va); + printf("\n(type 'yes' to confirm)? "); + fflush(stdout); + if (fgets(ansbuf, sizeof(ansbuf), stdin) == NULL) + return 0; + if (strcmp(ansbuf, "yes\n")) + return 0; + return 1; +} + +void +kdb5_update_princ_encryption(int argc, char *argv[]) +{ + struct update_enc_mkvno data = { 0 }; + char *name_pattern = NULL; + int force = 0; + int optchar; + krb5_error_code retval; + krb5_actkvno_node *actkvno_list = 0; + krb5_db_entry master_entry; + int nentries = 1; + krb5_boolean more = FALSE; + char *mkey_fullname = 0; +#ifdef BSD_REGEXPS + char *msg; +#endif + char *regexp = NULL; + krb5_keyblock *tmp_keyblock = NULL; + + while ((optchar = getopt(argc, argv, "fnv")) != -1) { + switch (optchar) { + case 'f': + force = 1; + break; + case 'n': + data.dry_run = 1; + break; + case 'v': + data.verbose = 1; + break; + case '?': + case ':': + default: + usage(); + } + } + if (argv[optind] != NULL) { + name_pattern = argv[optind]; + if (argv[optind+1] != NULL) + usage(); + } + + retval = krb5_unparse_name(util_context, master_princ, &mkey_fullname); + if (retval) { + com_err(progname, retval, "while formatting master principal name"); + exit_status++; + goto cleanup; + } + + if (master_keylist == NULL) { + com_err(progname, retval, "master keylist not initialized"); + exit_status++; + goto cleanup; + } + + /* The glob_to_regexp code only cares if the "realm" parameter is + NULL or not; the string data is irrelevant. */ + if (name_pattern == NULL) + name_pattern = "*"; + if (glob_to_regexp(name_pattern, "hi", ®exp) != 0) { + com_err(progname, ENOMEM, + "converting glob pattern '%s' to regular expression", + name_pattern); + exit_status++; + goto cleanup; + } + + 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) */ + com_err(progname, 0, "error compiling converted regexp '%s'", regexp); + exit_status++; + goto cleanup; + } + + retval = krb5_db_get_principal(util_context, master_princ, &master_entry, + &nentries, &more); + if (retval != 0) { + com_err(progname, retval, "while getting master key principal %s", + mkey_fullname); + exit_status++; + goto cleanup; + } + if (nentries != 1) { + com_err(progname, 0, + "cannot find master key principal %s in database!", + mkey_fullname); + exit_status++; + goto cleanup; + } + + retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, "while looking up active kvno list"); + exit_status++; + goto cleanup; + } + + /* Master key is always stored encrypted in the latest version of + itself. */ + new_mkvno = krb5_db_get_key_data_kvno(util_context, + master_entry.n_key_data, + master_entry.key_data); + + retval = krb5_dbe_find_mkey(util_context, master_keylist, + &master_entry, &tmp_keyblock); + if (retval) { + com_err(progname, retval, "retrieving the most recent master key"); + exit_status++; + goto cleanup; + } + new_master_keyblock = *tmp_keyblock; + + if (!force && + !data.dry_run && + !are_you_sure("Re-encrypt all keys not using master key vno %u?", + new_mkvno)) { + printf("OK, doing nothing.\n"); + exit_status++; + goto cleanup; + } + if (data.verbose) { + if (data.dry_run) + printf("Principals whose keys WOULD BE re-encrypted to master key vno %u:\n", + new_mkvno); + else + printf("Principals whose keys are being re-encrypted to master key vno %u if necessary:\n", + new_mkvno); + } + + retval = krb5_db_iterate(util_context, name_pattern, + update_princ_encryption_1, &data); + /* If exit_status is set, then update_princ_encryption_1 already + printed a message. */ + if (retval != 0 && exit_status == 0) { + com_err(progname, retval, "trying to process principal database"); + exit_status++; + } + (void) krb5_db_fini(util_context); + if (data.dry_run) + printf("%u principals processed: %u would be updated, %u already current\n", + data.re_match_count, data.updated, data.already_current); + else + printf("%u principals processed: %u updated, %u already current\n", + data.re_match_count, data.updated, data.already_current); + +cleanup: + free(regexp); + memset(&new_master_keyblock, 0, sizeof(new_master_keyblock)); + krb5_free_keyblock(util_context, tmp_keyblock); + krb5_free_unparsed_name(util_context, mkey_fullname); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); +} + +struct kvnos_in_use { + krb5_kvno kvno; + unsigned int use_count; +}; + +struct purge_args { + krb5_context kcontext; + struct kvnos_in_use *kvnos; + unsigned int num_kvnos; +}; + +static krb5_error_code +find_mkvnos_in_use(krb5_pointer ptr, + krb5_db_entry *entry) +{ + krb5_error_code retval; + struct purge_args * args; + unsigned int i; + krb5_kvno mkvno; + + args = (struct purge_args *) ptr; + + retval = krb5_dbe_lookup_mkvno(args->kcontext, entry, &mkvno); + if (retval) + return (retval); + + for (i = 0; i < args->num_kvnos; i++) { + if (args->kvnos[i].kvno == mkvno) { + /* XXX do I need to worry about use_count wrapping? */ + args->kvnos[i].use_count++; + break; + } + } + return 0; +} + +void +kdb5_purge_mkeys(int argc, char *argv[]) +{ + int optchar; + krb5_error_code retval; + char *mkey_fullname = NULL; + krb5_timestamp now; + krb5_db_entry master_entry; + int nentries = 0; + krb5_boolean more = FALSE; + krb5_boolean force = FALSE, dry_run = FALSE, verbose = FALSE; + struct purge_args args; + char buf[5]; + unsigned int i, j, k, num_kvnos_inuse, num_kvnos_purged; + unsigned int old_key_data_count; + krb5_actkvno_node *actkvno_list = NULL, *actkvno_entry, *prev_actkvno_entry; + krb5_mkey_aux_node *mkey_aux_list = NULL, *mkey_aux_entry, *prev_mkey_aux_entry; + krb5_key_data *old_key_data; + + memset(&master_princ, 0, sizeof(master_princ)); + memset(&args, 0, sizeof(args)); + + optind = 1; + while ((optchar = getopt(argc, argv, "fnv")) != -1) { + switch(optchar) { + case 'f': + force = TRUE; + break; + case 'n': + dry_run = TRUE; /* mkey princ will not be modified */ + force = TRUE; /* implied */ + break; + case 'v': + verbose = TRUE; + break; + case '?': + default: + usage(); + 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(progname, retval, "while setting up master key name"); + exit_status++; + return; + } + + retval = krb5_db_get_principal(util_context, master_princ, &master_entry, + &nentries, &more); + if (retval != 0) { + com_err(progname, retval, + "while getting master key principal %s", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries == 0) { + com_err(progname, KRB5_KDB_NOENTRY, + "principal %s not found in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } else if (nentries > 1) { + com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, + "principal %s has multiple entries in Kerberos database", + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + if (!force) { + printf("Will purge all unused master keys stored in the '%s' principal, are you sure?\n", + mkey_fullname); + printf("(type 'yes' to confirm)? "); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + exit_status++; + goto cleanup_return; + } + if (strcmp(buf, "yes\n")) { + exit_status++; + goto cleanup_return; + } + printf("OK, purging unused master keys from '%s'...\n", mkey_fullname); + } + + /* save the old keydata */ + old_key_data_count = master_entry.n_key_data; + if (old_key_data_count == 1) { + if (verbose) + printf("There is only one master key which can not be purged.\n"); + goto cleanup_return; + } + old_key_data = master_entry.key_data; + + args.kvnos = (struct kvnos_in_use *) malloc(sizeof(struct kvnos_in_use) * old_key_data_count); + if (args.kvnos == NULL) { + retval = ENOMEM; + com_err(progname, ENOMEM, "while allocating args.kvnos"); + exit_status++; + goto cleanup_return; + } + memset(args.kvnos, 0, sizeof(struct kvnos_in_use) * old_key_data_count); + args.num_kvnos = old_key_data_count; + args.kcontext = util_context; + + /* populate the kvnos array with all the current mkvnos */ + for (i = 0; i < old_key_data_count; i++) + args.kvnos[i].kvno = master_entry.key_data[i].key_data_kvno; + + if ((retval = krb5_db_iterate(util_context, + NULL, + find_mkvnos_in_use, + (krb5_pointer) &args))) { + com_err(progname, retval, "while finding master keys in use"); + exit_status++; + goto cleanup_return; + } + /* + * args.kvnos has been marked with the mkvno's that are currently protecting + * princ entries + */ + if (dry_run) + printf("Would purge the follwing master key(s) from %s:\n", mkey_fullname); + else + printf("Purging the follwing master key(s) from %s:\n", mkey_fullname); + + /* find # of keys still in use or print out verbose info */ + for (i = num_kvnos_inuse = num_kvnos_purged = 0; i < args.num_kvnos; i++) { + if (args.kvnos[i].use_count > 0) { + num_kvnos_inuse++; + } else { + /* this key would be deleted */ + if (args.kvnos[i].kvno == master_kvno) { + com_err(progname, KRB5_KDB_STORED_MKEY_NOTCURRENT, + "master key stash file needs updating, command aborting"); + exit_status++; + goto cleanup_return; + } + num_kvnos_purged++; + printf("KNVO: %d\n", args.kvnos[i].kvno); + } + } + /* didn't find any keys to purge */ + if (num_kvnos_inuse == args.num_kvnos) { + printf("All keys in use, nothing purged.\n"); + goto cleanup_return; + } + if (dry_run) { + /* bail before doing anything else */ + printf("%d key(s) would be purged.\n", num_kvnos_purged); + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, "while looking up active kvno list"); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_mkey_aux(util_context, &master_entry, &mkey_aux_list); + if (retval != 0) { + com_err(progname, retval, "while looking up mkey aux data list"); + exit_status++; + goto cleanup_return; + } + + master_entry.key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) * num_kvnos_inuse); + if (master_entry.key_data == NULL) { + retval = ENOMEM; + com_err(progname, ENOMEM, "while allocating key_data"); + exit_status++; + goto cleanup_return; + } + memset((char *) master_entry.key_data, 0, sizeof(krb5_key_data) * num_kvnos_inuse); + master_entry.n_key_data = num_kvnos_inuse; /* there's only 1 mkey per kvno */ + + /* + * Assuming that the latest mkey will not be purged because it will always + * be "in use" so this code will not bother with encrypting keys again. + */ + for (i = k = 0; i < old_key_data_count; i++) { + for (j = 0; j < args.num_kvnos; j++) { + if (args.kvnos[j].kvno == (krb5_kvno) old_key_data[i].key_data_kvno) { + if (args.kvnos[j].use_count != 0) { + master_entry.key_data[k++] = old_key_data[i]; + break; + } else { + /* remove unused mkey */ + /* adjust the actkno data */ + for (prev_actkvno_entry = actkvno_entry = actkvno_list; + actkvno_entry != NULL; + actkvno_entry = actkvno_entry->next) { + + if (actkvno_entry->act_kvno == args.kvnos[j].kvno) { + if (actkvno_entry == actkvno_list) { + /* remove from head */ + actkvno_list = actkvno_entry->next; + prev_actkvno_entry = actkvno_list; + } else if (actkvno_entry->next == NULL) { + /* remove from tail */ + prev_actkvno_entry->next = NULL; + } else { + /* remove in between */ + prev_actkvno_entry->next = actkvno_entry->next; + } + actkvno_entry->next = NULL; + krb5_dbe_free_actkvno_list(util_context, actkvno_entry); + break; /* deleted entry, no need to loop further */ + } else { + prev_actkvno_entry = actkvno_entry; + } + } + /* adjust the mkey aux data */ + for (prev_mkey_aux_entry = mkey_aux_entry = mkey_aux_list; + mkey_aux_entry != NULL; + mkey_aux_entry = mkey_aux_entry->next) { + + if (mkey_aux_entry->mkey_kvno == args.kvnos[j].kvno) { + if (mkey_aux_entry == mkey_aux_list) { + mkey_aux_list = mkey_aux_entry->next; + prev_mkey_aux_entry = mkey_aux_list; + } else if (mkey_aux_entry->next == NULL) { + prev_mkey_aux_entry->next = NULL; + } else { + prev_mkey_aux_entry->next = mkey_aux_entry->next; + } + mkey_aux_entry->next = NULL; + krb5_dbe_free_mkey_aux_list(util_context, mkey_aux_entry); + break; /* deleted entry, no need to loop further */ + } else { + prev_mkey_aux_entry = mkey_aux_entry; + } + } + } + } + } + } + assert(k == num_kvnos_inuse); + + if ((retval = krb5_dbe_update_actkvno(util_context, &master_entry, + actkvno_list))) { + com_err(progname, retval, + "while updating actkvno data for master principal entry"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mkey_aux(util_context, &master_entry, + mkey_aux_list))) { + com_err(progname, retval, + "while updating mkey_aux data for master principal entry"); + exit_status++; + return; + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, "while getting current time"); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, &master_entry, + now, master_princ))) { + com_err(progname, retval, + "while updating the master key principal modification time"); + exit_status++; + goto cleanup_return; + } + + master_entry.mask |= KADM5_KEY_DATA; + + if ((retval = krb5_db_put_principal(util_context, &master_entry, &nentries))) { + (void) krb5_db_fini(util_context); + com_err(progname, retval, "while adding master key entry to the database"); + exit_status++; + goto cleanup_return; + } + printf("%d key(s) purged.\n", num_kvnos_purged); + +cleanup_return: + /* clean up */ + (void) krb5_db_fini(util_context); + krb5_free_principal(util_context, master_princ); + free(args.kvnos); + krb5_free_unparsed_name(util_context, mkey_fullname); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + krb5_dbe_free_mkey_aux_list(util_context, mkey_aux_list); + return; +} diff --git a/krb5-1-7/src/kadmin/dbutil/kdb5_stash.c b/krb5-1-7/src/kadmin/dbutil/kdb5_stash.c new file mode 100644 index 000000000..cdd947ac4 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_stash.c @@ -0,0 +1,191 @@ +/* + * 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 +#include +#include "kdb5_util.h" + +extern krb5_keyblock master_keyblock; +extern krb5_keylist_node *master_keylist; +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; + krb5_kvno mkey_kvno; + + retval = kadm5_init_krb5_context(&context); + if( retval ) + { + com_err(progname, retval, "while initializing krb5_context"); + exit(1); + } + + if ((retval = krb5_set_default_realm(context, + util_context->default_realm))) { + com_err(progname, 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(progname, KRB5_PROG_KEYTYPE_NOSUPP, + "while setting up enctype %d", master_keyblock.enctype); + else + com_err(progname, 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(progname, 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(progname, retval, "while initializing the database '%s'", + dbname); + exit_status++; return; + } + + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = IGNORE_VNO; /* use whatever krb5_db_fetch_mkey finds */ + + if (!valid_master_key) { + /* TRUE here means read the keyboard, but only once */ + retval = krb5_db_fetch_mkey(context, master_princ, + master_keyblock.enctype, + TRUE, FALSE, (char *) NULL, + &mkey_kvno, + NULL, &master_keyblock); + if (retval) { + com_err(progname, retval, "while reading master key"); + (void) krb5_db_fini(context); + exit_status++; return; + } + + retval = krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, mkey_kvno, + &master_keylist); + if (retval) { + com_err(progname, retval, "while getting master key list"); + (void) krb5_db_fini(context); + exit_status++; return; + } + } else { + printf("Using existing stashed keys to update stash file.\n"); + } + + retval = krb5_db_store_master_key_list(context, keyfile, master_princ, + master_keylist, NULL); + if (retval) { + com_err(progname, errno, "while storing key"); + (void) krb5_db_fini(context); + exit_status++; return; + } + + retval = krb5_db_fini(context); + if (retval) { + com_err(progname, retval, "closing database '%s'", dbname); + exit_status++; return; + } + + krb5_free_context(context); + exit_status = 0; + return; +} diff --git a/krb5-1-7/src/kadmin/dbutil/kdb5_util.M b/krb5-1-7/src/kadmin/dbutil/kdb5_util.M new file mode 100644 index 000000000..f566781eb --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_util.M @@ -0,0 +1,273 @@ +.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\-kv\fP\ \fImkeyVNO\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\-kv\fP\ \fImkeyVNO\fP +Specifies the version number of the master key in the database; the default is +1. Note that 0 is not allowed. +.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 +.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. +.RE +.TP +\fBark\fP +Adds a random key. +.TP +\fBadd_mkey\fP [\fB\-e etype\fP] [\fB\-s\fP] +Adds a new master key to the K/M (master key) principal. Existing master keys will remain. +The +.B \-e etype +option allows specification of the enctype of the new master key. The +.B \-s +option stashes the new master key in a local stash file which will be created if it doesn't already exist. +.TP +\fBuse_mkey\fP \fImkeyVNO [\fBtime\fP] +Sets the activation time of the master key specified by +.B mkeyVNO. +Once a master key is active (i.e. its activation time has been reached) it will then be used to encrypt principal keys either when the principal keys change, are newly created or when the update_princ_encryption command is run. If the +.B time +argument is provided then that will be the activation time otherwise the current time is used by default. The format of the optional +.B time +argument is that specified in the Time Formats section of the kadmin man page. +.TP +\fBlist_mkeys\fP +List all master keys from most recent to earliest in K/M principal. The output will show the KVNO, enctype and salt for each mkey similar to kadmin getprinc output. A * following an mkey denotes the currently active master key. +.TP +\fBpurge_mkeys\fP [\fB-f\fP] [\fB-n\fP] [\fB-v\fP] +Delete master keys from the K/M principal that are not used to protect any principals. This command can be used to remove old master keys from a K/M principal once all principal keys are protected by a newer master key. +.TP +.B \-f +does not prompt user. +.TP +.B \-n +do a dry run, shows master keys that would be purged, does not actually purge any keys. +.TP +.B \-v +verbose output. +.TP +\fBupdate_princ_encryption\fP [\fB\-f\fP] [\fB\-n\fP] [\fB\-v\fP] [\fBprinc\-pattern\fP] +Update all principal records (or only those matching the +.B princ\-pattern +glob pattern) to re-encrypt the key data using the active +database master key, if they are encrypted using older versions, +and give a count at the end of the number of principals updated. +If the +.B \-f +option is not given, ask for confirmation before starting to make +changes. The +.B \-v +option causes each principal processed (each one matching the pattern) +to be listed, and an indication given as to whether it needed updating +or not. +The +.B \-n +option causes the actions not to be taken, only the normal or verbose +status messages displayed; this implies +.B \-f +since no database changes will be performed and thus there's little +reason to seek confirmation. +.SH SEE ALSO +kadmin(8) diff --git a/krb5-1-7/src/kadmin/dbutil/kdb5_util.c b/krb5-1-7/src/kadmin/dbutil/kdb5_util.c new file mode 100644 index 000000000..6cb70c1cd --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_util.c @@ -0,0 +1,674 @@ +/* + * admin/edit/kdb5_edit.c + * + * (C) Copyright 1990,1991, 1996, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#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 [-kv mkeyVNO] [-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" + "\tadd_mkey [-e etype] [-s]\n" + "\tuse_mkey kvno [time]\n" + "\tlist_mkeys\n" + ); + /* avoid a string length compiler warning */ + fprintf(stderr, + "\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" + "\tpurge_mkeys [-f] [-n] [-v]\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; +krb5_kvno master_kvno; /* fetched */ +extern krb5_keylist_node *master_keylist; +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}, /* 1 opens the kdb */ + {"stash", kdb5_stash, 1}, + {"dump", dump_db, 1}, + {"load", load_db, 0}, + {"ark", add_random_key, 1}, + {"add_mkey", kdb5_add_mkey, 1}, + {"use_mkey", kdb5_use_mkey, 1}, + {"list_mkeys", kdb5_list_mkeys, 1}, + {"update_princ_encryption", kdb5_update_princ_encryption, 1}, + {"purge_mkeys", kdb5_purge_mkeys, 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); + + /* + * Ensure that "progname" is set before calling com_err. + */ + progname = (strrchr(argv[0], '/') ? + strrchr(argv[0], '/') + 1 : argv[0]); + + retval = kadm5_init_krb5_context(&util_context); + if (retval) { + com_err (progname, retval, "while initializing Kerberos code"); + exit(1); + } + + 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; + + if (asprintf(&db_name_tmp, "dbname=%s", global_params.dbname) < 0) + { + com_err(progname, ENOMEM, "while parsing command arguments"); + exit(1); + } + + 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(progname, EINVAL, ": %s is an invalid enctype", koptarg); + exit(1); + } else + global_params.mask |= KADM5_CONFIG_ENCTYPE; + } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) { + global_params.kvno = (krb5_kvno) atoi(koptarg); + if (global_params.kvno == IGNORE_VNO) { + com_err(progname, EINVAL, ": %s is an invalid mkeyVNO", koptarg); + exit(1); + } else + global_params.mask |= KADM5_CONFIG_KVNO; + } 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(progname, 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(progname, 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; + + if (global_params.iprop_enabled == TRUE) + ulog_set_role(util_context, IPROP_MASTER); + else + ulog_set_role(util_context, IPROP_NULL); + + (*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(progname, 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(progname, 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(progname, 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); + } + + if (global_params.mask & KADM5_CONFIG_KVNO) + master_kvno = global_params.kvno; /* user specified */ + else + master_kvno = IGNORE_VNO; + + /* 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"); + exit_status++; + 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"); + exit_status++; + 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, + &master_kvno, + 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 0 /************** Begin IFDEF'ed OUT *******************************/ + /* krb5_db_fetch_mkey_list will verify the mkey */ + if ((retval = krb5_db_verify_master_key(util_context, master_princ, + master_kvno, &master_keyblock))) { + com_err(progname, retval, "while verifying master key"); + exit_status++; + krb5_free_keyblock_contents(util_context, &master_keyblock); + return(1); + } +#endif /**************** END IFDEF'ed OUT *******************************/ + + if ((retval = krb5_db_fetch_mkey_list(util_context, master_princ, + &master_keyblock, master_kvno, + &master_keylist))) { + com_err(progname, retval, "while getting master key list"); + com_err(progname, 0, "Warning: proceeding without master key list"); + exit_status++; + return(0); + } + + seed.length = master_keyblock.length; + seed.data = (char *) 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); + krb5_db_free_mkey_list(util_context, master_keylist); + 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; + krb5_db_free_mkey_list(util_context, master_keylist); + 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 = progname; + char *ks_str = NULL; + char *pr_str; + krb5_keyblock *tmp_mkey; + + 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; + + /* Find the mkey used to protect the existing keys */ + ret = krb5_dbe_find_mkey(util_context, master_keylist, &dbent, &tmp_mkey); + if (ret) { + com_err(me, ret, "while finding mkey"); + exit_status++; + return; + } + + ret = krb5_dbe_ark(util_context, tmp_mkey, + 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-7/src/kadmin/dbutil/kdb5_util.h b/krb5-1-7/src/kadmin/dbutil/kdb5_util.h new file mode 100644 index 000000000..6e99ac378 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/kdb5_util.h @@ -0,0 +1,104 @@ +/* + * admin/edit/kdb5_edit.h + * + * Copyright 1992, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#define MAX_HEADER 1024 +#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 krb5_kvno new_mkvno; +extern krb5_keylist_node *master_keylist; +extern krb5_keyblock new_master_keyblock; +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 kdb5_create (int argc, char **argv); +extern void kdb5_destroy (int argc, char **argv); +extern void kdb5_stash (int argc, char **argv); +extern void kdb5_add_mkey (int argc, char **argv); +extern void kdb5_use_mkey (int argc, char **argv); +extern void kdb5_list_mkeys (int argc, char **argv); +extern void kdb5_update_princ_encryption (int argc, char **argv); +extern krb5_error_code master_key_convert(krb5_context context, + krb5_db_entry *db_entry); +extern void kdb5_purge_mkeys (int argc, char **argv); + +extern void update_ok_file (char *file_name); + +extern int kadm5_create (kadm5_config_params *params); + +extern krb5_error_code add_new_mkey(krb5_context, krb5_db_entry *, + krb5_keyblock *, krb5_kvno); + +extern krb5_kvno get_next_kvno(krb5_context, krb5_db_entry *); + +void usage (void); + diff --git a/krb5-1-7/src/kadmin/dbutil/nstrtok.h b/krb5-1-7/src/kadmin/dbutil/nstrtok.h new file mode 100644 index 000000000..f7f0d4a69 --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/nstrtok.h @@ -0,0 +1,3 @@ +/* Prototype for nstrtok */ +char *nstrtok(char *, const char *delim); + diff --git a/krb5-1-7/src/kadmin/dbutil/ovload.c b/krb5-1-7/src/kadmin/dbutil/ovload.c new file mode 100644 index 000000000..46036478f --- /dev/null +++ b/krb5-1-7/src/kadmin/dbutil/ovload.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include "autoconf.h" +#ifdef HAVE_MEMORY_H +#include +#endif + +#include +#include +#include +#include +#include "import_err.h" +#include "kdb5_util.h" +#include "nstrtok.h" + +#define LINESIZE 32768 /* XXX */ + +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: + * 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 = 0; + 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 = strdup(cp)) == NULL) { + ret = ENOMEM; + goto done; + } + } 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-7/src/kadmin/dbutil/string_table.c b/krb5-1-7/src/kadmin/dbutil/string_table.c new file mode 100644 index 000000000..1caa1402e --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/dbutil/string_table.h b/krb5-1-7/src/kadmin/dbutil/string_table.h new file mode 100644 index 000000000..b89b9f1fa --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/dbutil/strtok.c b/krb5-1-7/src/kadmin/dbutil/strtok.c new file mode 100644 index 000000000..80117a31b --- /dev/null +++ b/krb5-1-7/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 +#include +#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 + * 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-7/src/kadmin/deps b/krb5-1-7/src/kadmin/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/kadmin/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/kadmin/kdbkeys/Makefile.in b/krb5-1-7/src/kadmin/kdbkeys/Makefile.in new file mode 100644 index 000000000..741a9a745 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/kdbkeys/do-test.pl b/krb5-1-7/src/kadmin/kdbkeys/do-test.pl new file mode 100755 index 000000000..7acb425f7 --- /dev/null +++ b/krb5-1-7/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 = ); + if ($header ne "kdb5_util load_dump version 4") { + die "Cannot operate on dump version \"$header\"; version 4 required."; + } + while() { + 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-7/src/kadmin/ktutil/Makefile.in b/krb5-1-7/src/kadmin/ktutil/Makefile.in new file mode 100644 index 000000000..c9b7d48fd --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/Makefile.in @@ -0,0 +1,39 @@ +thisconfigdir=../.. +myfulldir=kadmin/ktutil +mydir=kadmin/ktutil +BUILDTOP=$(REL)..$(S).. +PROG_LIBPATH=-L$(TOPLIBD) +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}$(CLIENT_BINDIR)/ktutil + $(INSTALL_DATA) $(srcdir)/ktutil.M ${DESTDIR}$(CLIENT_MANDIR)/ktutil.1 + +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 diff --git a/krb5-1-7/src/kadmin/ktutil/deps b/krb5-1-7/src/kadmin/ktutil/deps new file mode 100644 index 000000000..6b394b89f --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/deps @@ -0,0 +1,26 @@ +# +# Generated makefile dependencies follow. +# +$(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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/kadmin/ktutil/ktutil.M b/krb5-1-7/src/kadmin/ktutil/ktutil.M new file mode 100644 index 000000000..7086a5a16 --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/ktutil.M @@ -0,0 +1,67 @@ +.TH KTUTIL 1 +.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-7/src/kadmin/ktutil/ktutil.c b/krb5-1-7/src/kadmin/ktutil/ktutil.c new file mode 100644 index 000000000..5a6ee783b --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/ktutil.c @@ -0,0 +1,280 @@ +/* + * kadmin/ktutil/ktutil.c + * + * Copyright 1995, 1996, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include "adm_proto.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#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[]; +{ + 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]); +} + +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[]; +{ + fprintf(stderr, "%s: writing srvtabs is no longer supported\n", argv[0]); +} + +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; + + tstamp = lp->entry->timestamp; + (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"); + free(pname); + } +} + + + + + + + + + + diff --git a/krb5-1-7/src/kadmin/ktutil/ktutil.h b/krb5-1-7/src/kadmin/ktutil/ktutil.h new file mode 100644 index 000000000..5ecc7d4ad --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/ktutil.h @@ -0,0 +1,70 @@ +/* + * 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 *); + +krb5_error_code ktutil_read_srvtab (krb5_context, + char *, + krb5_kt_list *); + +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-7/src/kadmin/ktutil/ktutil_ct.ct b/krb5-1-7/src/kadmin/ktutil/ktutil_ct.ct new file mode 100644 index 000000000..0c7ccb689 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/ktutil/ktutil_funcs.c b/krb5-1-7/src/kadmin/ktutil/ktutil_funcs.c new file mode 100644 index 000000000..168087518 --- /dev/null +++ b/krb5-1-7/src/kadmin/ktutil/ktutil_funcs.c @@ -0,0 +1,351 @@ +/* + * 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" +#include +#include + +/* + * 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; + } + + snprintf(promptstr, sizeof(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; + int result; + + result = snprintf(ktname, sizeof(ktname), "WRFILE:%s", name); + if (SNPRINTF_OVERFLOW(result, sizeof(ktname))) + return ENAMETOOLONG; + 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; +} + +/* + * 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; +{ + char *ktname; + krb5_error_code result; + + if (asprintf(&ktname, "SRVTAB:%s", name) < 0) + return ENOMEM; + result = ktutil_read_keytab(context, ktname, list); + free(ktname); + return result; +} diff --git a/krb5-1-7/src/kadmin/passwd/Kpasswd b/krb5-1-7/src/kadmin/passwd/Kpasswd new file mode 100644 index 000000000..a7ec03161 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/Makefile.in b/krb5-1-7/src/kadmin/passwd/Makefile.in new file mode 100644 index 000000000..e6469c85d --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/Makefile.in @@ -0,0 +1,26 @@ +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) +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) diff --git a/krb5-1-7/src/kadmin/passwd/deps b/krb5-1-7/src/kadmin/passwd/deps new file mode 100644 index 000000000..ff09f598f --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/deps @@ -0,0 +1,26 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)tty_kpasswd.$(OBJEXT): $(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/kdb.h \ + $(SRCTOP)/include/krb5.h kpasswd.h kpasswd_strings.h \ + tty_kpasswd.c +$(OUTPRE)kpasswd.$(OBJEXT): $(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/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-7/src/kadmin/passwd/kpasswd.M b/krb5-1-7/src/kadmin/passwd/kpasswd.M new file mode 100644 index 000000000..185c1f595 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/kpasswd.c b/krb5-1-7/src/kadmin/passwd/kpasswd.c new file mode 100644 index 000000000..ca47fca5b --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/kpasswd.c @@ -0,0 +1,281 @@ +/* + * Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Header$ + * + * + */ + +static char rcsid[] = "$Id$"; + +#include +#include + +#include "kpasswd_strings.h" +#define string_text error_message + +#include "kpasswd.h" + +#include +#include +#include + +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-7/src/kadmin/passwd/kpasswd.h b/krb5-1-7/src/kadmin/passwd/kpasswd.h new file mode 100644 index 000000000..577ab386f --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/kpasswd_strings.et b/krb5-1-7/src/kadmin/passwd/kpasswd_strings.et new file mode 100644 index 000000000..7e826d270 --- /dev/null +++ b/krb5-1-7/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." +# /* */ + +# /* 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." +# /* , . */ + +# /* 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-7/src/kadmin/passwd/tty_kpasswd.c b/krb5-1-7/src/kadmin/passwd/tty_kpasswd.c new file mode 100644 index 000000000..189409140 --- /dev/null +++ b/krb5-1-7/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 +#include + +#include "kpasswd_strings.h" +#define string_text error_message + +#include "kpasswd.h" +#include +#include +#include + +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-7/src/kadmin/passwd/unit-test/Makefile.in b/krb5-1-7/src/kadmin/passwd/unit-test/Makefile.in new file mode 100644 index 000000000..37dfaca33 --- /dev/null +++ b/krb5-1-7/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@ VALGRIND="$(VALGRIND)" + +unit-test-setup:: + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) + +unit-test-cleanup:: + $(ENV_SETUP) $(STOP_SERVERS) +clean:: + $(RM) dbg.log kpasswd.sum kpasswd.log diff --git a/krb5-1-7/src/kadmin/passwd/unit-test/config/unix.exp b/krb5-1-7/src/kadmin/passwd/unit-test/config/unix.exp new file mode 100644 index 000000000..479d77243 --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/unit-test/config/unix.exp @@ -0,0 +1,115 @@ +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. +#&&![string match "/bin/sh" $arg] sh is used to start kadmind! + if [string match "/" [string index $arg 0]]&&![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 + } +} + +# +# 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 \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-7/src/kadmin/passwd/unit-test/deps b/krb5-1-7/src/kadmin/passwd/unit-test/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/unit-test/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp new file mode 100644 index 000000000..3d7dc4bfd --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp @@ -0,0 +1,113 @@ +# +# $Id$ +# + +set timeout 15 + +load_lib "helpers.exp" + +if [info exist env(DEBUG)] { debug 1 } + +# +# Here are the tests +# + +set pol2_time [timestamp] + +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 + +# Under "make check", init_db will just have been run and we could +# jump right into the too-soon test. But if someone is working with +# the test suite manually, init_db may have been run a while ago. +# So, force some known state, first. +set delay [expr $pol2_time + 11 - [timestamp]] +verbose "(sleeping $delay seconds so pol2 password can be changed)" +sleep $delay + +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.} + +# Now delay a little longer (if needed) and try changing pol2's +# password again. +verbose "(sleeping 10 seconds)" +sleep 10 + +test_win {pol2} {password min life passed} pol2 polbbbbbb pol222222 diff --git a/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp new file mode 100644 index 000000000..2cda17a6a --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp new file mode 100644 index 000000000..01b2296fc --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp @@ -0,0 +1,87 @@ +# +# $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) +} + +# Apple (in Mac OS X 10.5.4) is shipping a tcl in which +# unsetting env-array values seems not to work! +if {[info exists env(KRB5CCNAME)]} { + untested {B.7: default nonexisting ccache(1) (unset failed, tcl defective!)} + untested {B.7: default nonexisting ccache(2)} + untested {B.4: default existing cache containing existing principal} + set test2pass test2 + +} else { + + +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 test2pass newpass +} + +set env(KRB5CCNAME) FILE:/tmp/ovsec_adm_test_ccache +kinit test2 $test2pass +test_win {} {B.3: specified existing cache containing existing principal} \ + test2 $test2pass test2 +kdestroy +unset env(KRB5CCNAME) + +# Apple (in Mac OS X 10.5.4) is shipping a tcl in which +# unsetting env-array values seems not to work! +if {[info exists env(KRB5CCNAME)]} { + untested {B.14: existing principal, no realm} + untested {B.15, C.6: non-existent principal, no realm} + untested {B.16: existing principal, with realm} + untested {B.17: non-existent principal, with realm} + +} else { + +#### 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-7/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp b/krb5-1-7/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp new file mode 100644 index 000000000..e132bab2f --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/unit-test/lib/helpers.exp b/krb5-1-7/src/kadmin/passwd/unit-test/lib/helpers.exp new file mode 100644 index 000000000..25b71a20e --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/passwd/xm_kpasswd.c b/krb5-1-7/src/kadmin/passwd/xm_kpasswd.c new file mode 100644 index 000000000..2f0bdf9c2 --- /dev/null +++ b/krb5-1-7/src/kadmin/passwd/xm_kpasswd.c @@ -0,0 +1,445 @@ +/* + * Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Header$ + * + * + */ + +static char rcsid_2[] = "$Id$"; + +#include +#include + +#include "kpasswd_strings.h" +#define string_text error_message +#define initialize_kpasswd_strings initialize_kpws_error_table + +#include +#include +#include + +char *whoami; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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. + */ + +#include + +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) + { + vsnprintf(buf + strlen(buf), sizeof(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]; + + snprintf(buf, sizeof(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-7/src/kadmin/scripts/inst-hdrs.sh b/krb5-1-7/src/kadmin/scripts/inst-hdrs.sh new file mode 100755 index 000000000..242be89e9 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/server/Makefile.in b/krb5-1-7/src/kadmin/server/Makefile.in new file mode 100644 index 000000000..21f3e7aea --- /dev/null +++ b/krb5-1-7/src/kadmin/server/Makefile.in @@ -0,0 +1,29 @@ +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 \ + -I$(SRCTOP)/lib/kadm5/srv + +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 ipropd_svc.o network.o +SRCS = kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c misc.c server_glue_v1.c ipropd_svc.c network.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) diff --git a/krb5-1-7/src/kadmin/server/deps b/krb5-1-7/src/kadmin/server/deps new file mode 100644 index 000000000..d1303b89c --- /dev/null +++ b/krb5-1-7/src/kadmin/server/deps @@ -0,0 +1,143 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.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/kdb.h $(SRCTOP)/include/krb5.h kadm_rpc_svc.c \ + misc.h +$(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.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/kdb.h \ + $(SRCTOP)/include/krb5.h misc.h server_stubs.c +$(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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/kdb_log.h $(SRCTOP)/include/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/gssapi/generic/gssapiP_generic.h $(SRCTOP)/lib/gssapi/generic/gssapi_ext.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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.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_acl.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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/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/kdb.h \ + $(SRCTOP)/include/krb5.h misc.h server_glue_v1.c +$(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.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 \ + $(BUILDTOP)/include/osconf.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_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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \ + $(SRCTOP)/include/kdb_log.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/lib/kadm5/srv/server_acl.h ipropd_svc.c misc.h +$(OUTPRE)network.$(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_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/cm.h $(SRCTOP)/include/fake-addrinfo.h \ + $(SRCTOP)/include/foreachaddr.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/iprop.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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.h network.c diff --git a/krb5-1-7/src/kadmin/server/ipropd_svc.c b/krb5-1-7/src/kadmin/server/ipropd_svc.c new file mode 100644 index 000000000..e00701b0c --- /dev/null +++ b/krb5-1-7/src/kadmin/server/ipropd_svc.c @@ -0,0 +1,611 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)ipropd_svc.c 1.2 04/02/20 SMI" */ + + +#include +#include /* getenv, exit */ +#include +#include +#include /* rlimit */ +#include + +#include "k5-platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "osconf.h" + +extern gss_name_t rqst2name(struct svc_req *rqstp); + +extern void *global_server_handle; +extern int nofork; +extern short l_port; +static char abuf[33]; + +/* Result is stored in a static buffer and is invalidated by the next call. */ +static const char *client_addr(struct svc_req *svc) { + strlcpy(abuf, inet_ntoa(svc->rq_xprt->xp_raddr.sin_addr), sizeof(abuf)); + return abuf; +} + +static char *reply_ok_str = "UPDATE_OK"; +static char *reply_err_str = "UPDATE_ERROR"; +static char *reply_fr_str = "UPDATE_FULL_RESYNC_NEEDED"; +static char *reply_busy_str = "UPDATE_BUSY"; +static char *reply_nil_str = "UPDATE_NIL"; +static char *reply_perm_str = "UPDATE_PERM_DENIED"; +static char *reply_unknown_str = ""; + +#define LOG_UNAUTH _("Unauthorized request: %s, client=%s, service=%s, addr=%s") +#define LOG_DONE _("Request: %s, %s, %s, client=%s, service=%s, addr=%s") + +#ifdef DPRINT +#undef DPRINT +#endif +#define DPRINT(i) if (nofork) printf i + + +static void +debprret(char *w, update_status_t ret, kdb_sno_t sno) +{ + switch (ret) { + case UPDATE_OK: + printf("%s: end (OK, sno=%u)\n", + w, sno); + break; + case UPDATE_ERROR: + printf("%s: end (ERROR)\n", w); + break; + case UPDATE_FULL_RESYNC_NEEDED: + printf("%s: end (FR NEEDED)\n", w); + break; + case UPDATE_BUSY: + printf("%s: end (BUSY)\n", w); + break; + case UPDATE_NIL: + printf("%s: end (NIL)\n", w); + break; + case UPDATE_PERM_DENIED: + printf("%s: end (PERM)\n", w); + break; + default: + printf("%s: end (UNKNOWN return code (%d))\n", w, ret); + } +} + +static char * +replystr(update_status_t ret) +{ + switch (ret) { + case UPDATE_OK: + return (reply_ok_str); + case UPDATE_ERROR: + return (reply_err_str); + case UPDATE_FULL_RESYNC_NEEDED: + return (reply_fr_str); + case UPDATE_BUSY: + return (reply_busy_str); + case UPDATE_NIL: + return (reply_nil_str); + case UPDATE_PERM_DENIED: + return (reply_perm_str); + default: + return (reply_unknown_str); + } +} + +/* Returns null on allocation failure. + Regardless of success or failure, frees the input buffer. */ +static char * +buf_to_string(gss_buffer_desc *b) +{ + OM_uint32 min_stat; + char *s = malloc(b->length+1); + + if (s) { + memcpy(s, b->value, b->length); + s[b->length] = 0; + } + (void) gss_release_buffer(&min_stat, b); + return s; +} + +kdb_incr_result_t * +iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp) +{ + static kdb_incr_result_t ret; + char *whoami = "iprop_get_updates_1"; + int kret; + kadm5_server_handle_t handle = global_server_handle; + char *client_name = 0, *service_name = 0; + char obuf[256] = {0}; + + /* default return code */ + ret.ret = UPDATE_ERROR; + + DPRINT(("%s: start, last_sno=%lu\n", whoami, + (unsigned long) arg->last_sno)); + + if (!handle) { + krb5_klog_syslog(LOG_ERR, + _("%s: server handle is NULL"), + whoami); + goto out; + } + + { + gss_buffer_desc client_desc, service_desc; + + if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: setup_gss_names failed"), + whoami); + goto out; + } + client_name = buf_to_string(&client_desc); + service_name = buf_to_string(&service_desc); + if (client_name == NULL || service_name == NULL) { + free(client_name); + free(service_name); + krb5_klog_syslog(LOG_ERR, + "%s: out of memory recording principal names", + whoami); + goto out; + } + } + + DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", + whoami, client_name, service_name)); + + if (!kadm5int_acl_check(handle->context, + rqst2name(rqstp), + ACL_IPROP, + NULL, + NULL)) { + ret.ret = UPDATE_PERM_DENIED; + + krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami, + client_name, service_name, + client_addr(rqstp)); + goto out; + } + + kret = ulog_get_entries(handle->context, *arg, &ret); + + if (ret.ret == UPDATE_OK) { + (void) snprintf(obuf, sizeof (obuf), + _("%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu"), + replystr(ret.ret), + (unsigned long)arg->last_sno, + (unsigned long)ret.lastentry.last_sno); + } else { + (void) snprintf(obuf, sizeof (obuf), + _("%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A"), + replystr(ret.ret), + (unsigned long)arg->last_sno); + } + + krb5_klog_syslog(LOG_NOTICE, + _("Request: %s, %s, %s, client=%s, service=%s, addr=%s"), + whoami, + obuf, + ((kret == 0) ? "success" : error_message(kret)), + client_name, service_name, + client_addr(rqstp)); + +out: + if (nofork) + debprret(whoami, ret.ret, ret.lastentry.last_sno); + free(client_name); + free(service_name); + return (&ret); +} + + +/* + * Given a client princ (foo/fqdn@R), copy (in arg cl) the fqdn substring. + * Return arg cl str ptr on success, else NULL. + */ +static char * +getclhoststr(char *clprinc, char *cl, size_t len) +{ + char *s; + if ((s = strchr(clprinc, '/')) != NULL) { + /* XXX "!++s"? */ + if (!++s) + return NULL; + if (strlcpy(cl, s, len) >= len) + return NULL; + /* XXX Copy with @REALM first, with bounds check, then + chop off the realm?? */ + if ((s = strchr(cl, '@')) != NULL) { + *s = '\0'; + return (cl); /* success */ + } + } + + return (NULL); +} + +kdb_fullresync_result_t * +iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp) +{ + static kdb_fullresync_result_t ret; + char *tmpf = 0; + char *ubuf = 0; + char clhost[MAXHOSTNAMELEN] = {0}; + int pret, fret; + kadm5_server_handle_t handle = global_server_handle; + OM_uint32 min_stat; + gss_name_t name = NULL; + char *client_name = NULL, *service_name = NULL; + char *whoami = "iprop_full_resync_1"; + + /* default return code */ + ret.ret = UPDATE_ERROR; + + if (!handle) { + krb5_klog_syslog(LOG_ERR, + _("%s: server handle is NULL"), + whoami); + goto out; + } + + DPRINT(("%s: start\n", whoami)); + + { + gss_buffer_desc client_desc, service_desc; + + if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: setup_gss_names failed"), + whoami); + goto out; + } + client_name = buf_to_string(&client_desc); + service_name = buf_to_string(&service_desc); + if (client_name == NULL || service_name == NULL) { + free(client_name); + free(service_name); + krb5_klog_syslog(LOG_ERR, + "%s: out of memory recording principal names", + whoami); + goto out; + } + } + + DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", + whoami, client_name, service_name)); + + if (!kadm5int_acl_check(handle->context, + rqst2name(rqstp), + ACL_IPROP, + NULL, + NULL)) { + ret.ret = UPDATE_PERM_DENIED; + + krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami, + client_name, service_name, + client_addr(rqstp)); + goto out; + } + + if (!getclhoststr(client_name, clhost, sizeof (clhost))) { + krb5_klog_syslog(LOG_ERR, + _("%s: getclhoststr failed"), + whoami); + goto out; + } + + /* + * construct db dump file name; kprop style name + clnt fqdn + */ + if (asprintf(&tmpf, "%s_%s", KPROP_DEFAULT_FILE, clhost) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: unable to construct db dump file name; out of memory"), + whoami); + goto out; + } + + /* + * note the -i; modified version of kdb5_util dump format + * to include sno (serial number) + */ + if (asprintf(&ubuf, "%s dump -i %s &1", + KPROPD_DEFAULT_KDB5_UTIL, tmpf) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: cannot construct kdb5 util dump string too long; out of memory"), + whoami); + goto out; + } + + /* + * Fork to dump the db and xfer it to the slave. + * (the fork allows parent to return quickly and the child + * acts like a callback to the slave). + */ + fret = fork(); + DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid())); + + switch (fret) { + case -1: /* error */ + if (nofork) { + perror(whoami); + } + krb5_klog_syslog(LOG_ERR, + _("%s: fork failed: %s"), + whoami, + error_message(errno)); + goto out; + + case 0: /* child */ + DPRINT(("%s: run `%s' ...\n", whoami, ubuf)); + (void) signal(SIGCHLD, SIG_DFL); + /* run kdb5_util(1M) dump for IProp */ + /* XXX popen can return NULL; is pclose(NULL) okay? */ + pret = pclose(popen(ubuf, "w")); + DPRINT(("%s: pclose=%d\n", whoami, pret)); + if (pret != 0) { + /* XXX popen/pclose may not set errno + properly, and the error could be from the + subprocess anyways. */ + if (nofork) { + perror(whoami); + } + krb5_klog_syslog(LOG_ERR, + _("%s: pclose(popen) failed: %s"), + whoami, + error_message(errno)); + goto out; + } + + DPRINT(("%s: exec `kprop -f %s %s' ...\n", + whoami, tmpf, clhost)); + /* XXX Yuck! */ + if (getenv("KPROP_PORT")) + pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf, + "-P", getenv("KPROP_PORT"), + clhost, NULL); + else + pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf, + clhost, NULL); + if (pret == -1) { + if (nofork) { + perror(whoami); + } + krb5_klog_syslog(LOG_ERR, + _("%s: exec failed: %s"), + whoami, + error_message(errno)); + goto out; + } + + default: /* parent */ + ret.ret = UPDATE_OK; + /* not used by slave (sno is retrieved from kdb5_util dump) */ + ret.lastentry.last_sno = 0; + ret.lastentry.last_time.seconds = 0; + ret.lastentry.last_time.useconds = 0; + + krb5_klog_syslog(LOG_NOTICE, + _("Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s"), + whoami, fret, + client_name, service_name, + client_addr(rqstp)); + + goto out; + } + +out: + if (nofork) + debprret(whoami, ret.ret, 0); + free(client_name); + free(service_name); + if (name) + gss_release_name(&min_stat, &name); + free(tmpf); + free(ubuf); + return (&ret); +} + +static int +check_iprop_rpcsec_auth(struct svc_req *rqstp) +{ + /* XXX Since the client can authenticate against any principal in + the database, we need to do a sanity check. Only checking for + "kiprop" now, but that means theoretically the client could be + authenticating to kiprop on some other machine. */ + /* Code taken from kadm_rpc_svc.c, tweaked. */ + + 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_1(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("kiprop", c1->data, c1->length) == 0) { + success = 1; + } + +fail_princ: + if (!success) { + krb5_klog_syslog(LOG_ERR, "bad service principal %.*s%s", + (int) slen, (char *) 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; +} + +void +krb5_iprop_prog_1(struct svc_req *rqstp, + register SVCXPRT *transp) +{ + union { + kdb_last_t iprop_get_updates_1_arg; + } argument; + char *result; + bool_t (*_xdr_argument)(), (*_xdr_result)(); + char *(*local)(/* union XXX *, struct svc_req * */); + char *whoami = "krb5_iprop_prog_1"; + + if (!check_iprop_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 IPROP_GET_UPDATES: + _xdr_argument = xdr_kdb_last_t; + _xdr_result = xdr_kdb_incr_result_t; + local = (char *(*)()) iprop_get_updates_1_svc; + break; + + case IPROP_FULL_RESYNC: + _xdr_argument = xdr_void; + _xdr_result = xdr_kdb_fullresync_result_t; + local = (char *(*)()) iprop_full_resync_1_svc; + break; + + default: + krb5_klog_syslog(LOG_ERR, + _("RPC unknown request: %d (%s)"), + rqstp->rq_proc, whoami); + svcerr_noproc(transp); + return; + } + (void) memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_getargs failed (%s)"), + whoami); + svcerr_decode(transp); + return; + } + result = (*local)(&argument, rqstp); + + if (_xdr_result && result != NULL && + !svc_sendreply(transp, _xdr_result, result)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_sendreply failed (%s)"), + whoami); + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_freeargs failed (%s)"), + whoami); + + exit(1); + } + + if (rqstp->rq_proc == IPROP_GET_UPDATES) { + /* LINTED */ + kdb_incr_result_t *r = (kdb_incr_result_t *)result; + + if (r->ret == UPDATE_OK) { + ulog_free_entries(r->updates.kdb_ulog_t_val, + r->updates.kdb_ulog_t_len); + r->updates.kdb_ulog_t_val = NULL; + r->updates.kdb_ulog_t_len = 0; + } + } + +} + +#if 0 +/* + * Get the host base service name for the kiprop principal. Returns + * KADM5_OK on success. Caller must free the storage allocated for + * host_service_name. + */ +kadm5_ret_t +kiprop_get_adm_host_srv_name(krb5_context context, + const char *realm, + char **host_service_name) +{ + kadm5_ret_t ret; + char *name; + char *host; + + if (ret = kadm5_get_master(context, realm, &host)) + return (ret); + + if (asprintf(&name, "%s@%s", KIPROP_SVC_NAME, host) < 0) { + free(host); + return (ENOMEM); + } + free(host); + *host_service_name = name; + + return (KADM5_OK); +} +#endif diff --git a/krb5-1-7/src/kadmin/server/kadm_rpc_svc.c b/krb5-1-7/src/kadmin/server/kadm_rpc_svc.c new file mode 100644 index 000000000..4d4df89b8 --- /dev/null +++ b/krb5-1-7/src/kadmin/server/kadm_rpc_svc.c @@ -0,0 +1,338 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + */ + +#include +#include +#include /* for gss_nt_krb5_name */ +#include +#include +#include "autoconf.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include "misc.h" +#include "kadm5/server_internal.h" + +extern void *global_server_handle; + +static int check_rpcsec_auth(struct svc_req *); + +/* + * Function: kadm_1 + * + * Purpose: RPC proccessing procedure. + * originally generated from rpcgen + * + * Arguments: + * rqstp (input) rpc request structure + * transp (input) rpc transport structure + * (input/output) + * + * + * 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_1(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", + (int) slen, (char *) 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; +} + +int +gss_to_krb5_name_1(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-7/src/kadmin/server/kadmind.M b/krb5-1-7/src/kadmin/server/kadmind.M new file mode 100644 index 000000000..2a227fb4e --- /dev/null +++ b/krb5-1-7/src/kadmin/server/kadmind.M @@ -0,0 +1,296 @@ +.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. +.PP +kadmind can be configured for incremental database propagation. +Incremental propagation allows slave KDC servers to receive principal +and policy updates incrementally instead of receiving full dumps of +the database. This facility can be enabled in the +.I kdc.conf +file with the +.I iprop_enable +option. See the +.I kdc.conf +documentation for other options for tuning incremental propagation +parameters. Incremental propagation requires the principal +"kiprop/MASTER@REALM" (where MASTER is the master KDC's canonical host +name, and REALM the realm name) to be registered in the database. + +.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= +.fi +specifies the number of connections to be maintained per LDAP server. + +.nf +\-x host= +specifies the LDAP server to connect to by a LDAP URI. + +\-x 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= +.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 p +[Dis]allows the propagation of the principal 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'.kadm5.lock\ 'u" +principal.db +default name for Kerberos principal database +.TP +.kadm5 +KADM5 administrative database. (This would be "principal.kadm5", if you +use the default database name.) Contains policy information. +.TP +.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-7/src/kadmin/server/misc.c b/krb5-1-7/src/kadmin/server/misc.c new file mode 100644 index 000000000..1725fbf7d --- /dev/null +++ b/krb5-1-7/src/kadmin/server/misc.c @@ -0,0 +1,225 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#include +#include +#include +#include +#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. + * 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 + * 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 client, + krb5_principal target, + krb5_boolean initial_flag, + char *new_pw, char **ret_pw, + char *msg_ret, unsigned int msg_len) +{ + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + krb5_boolean access_granted; + krb5_boolean self; + + /* + * If no target is explicitly provided, then the target principal + * is the client principal. + */ + if (target == NULL) + target = client; + + /* + * A principal can always change its own password, as long as it + * has an initial ticket and meets the minimum password lifetime + * requirement. + */ + self = krb5_principal_compare(handle->context, client, target); + if (self) { + ret = check_min_life(server_handle, target, msg_ret, msg_len); + if (ret != 0) + return ret; + + access_granted = initial_flag; + } else + access_granted = FALSE; + + if (!access_granted && + kadm5int_acl_check_krb(handle->context, client, + ACL_CHANGEPW, target, NULL)) { + /* + * Otherwise, principals with appropriate privileges can change + * any password + */ + access_granted = TRUE; + } + + if (access_granted) { + ret = kadm5_chpass_principal_util(server_handle, + target, + new_pw, ret_pw, + msg_ret, msg_len); + } else { + ret = KADM5_AUTH_CHANGEPW; + strlcpy(msg_ret, "Unauthorized request", msg_len); + } + + return ret; +} + +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'; + snprintf(msg_ret, msg_len, 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-7/src/kadmin/server/misc.h b/krb5-1-7/src/kadmin/server/misc.h new file mode 100644 index 000000000..b8aef57f1 --- /dev/null +++ b/krb5-1-7/src/kadmin/server/misc.h @@ -0,0 +1,97 @@ +/* + * Copyright 1994 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#ifndef _MISC_H +#define _MISC_H 1 + +typedef struct _krb5_fulladdr { + krb5_address * address; + krb5_ui_4 port; +} krb5_fulladdr; + +void +log_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, char *data); + +int +setup_gss_names(struct svc_req *, gss_buffer_desc *, + gss_buffer_desc *); + + +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 client, + krb5_principal target, krb5_boolean initial_flag, + 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, + krb5_keytab keytab, + krb5_fulladdr *local_faddr, + krb5_fulladdr *remote_faddr, + krb5_data *req, krb5_data *rep); + +void kadm_1(struct svc_req *, SVCXPRT *); +void krb5_iprop_prog_1(struct svc_req *, SVCXPRT *); + +void trunc_name(size_t *len, char **dots); + +int +gss_to_krb5_name_1(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name, + krb5_principal *princ, gss_buffer_t gss_str); + + +extern volatile int signal_request_exit; +extern volatile int signal_request_hup; + +void reset_db(void); + +void log_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, char *data); + +/* network.c */ +krb5_error_code setup_network(void *handle, const char *prog); +krb5_error_code listen_and_process(void *handle, const char *prog); +krb5_error_code closedown_network(void *handle, const char *prog); + + +void +krb5_iprop_prog_1(struct svc_req *rqstp, SVCXPRT *transp); + +kadm5_ret_t +kiprop_get_adm_host_srv_name(krb5_context, + const char *, + char **); + + +#endif /* _MISC_H */ diff --git a/krb5-1-7/src/kadmin/server/network.c b/krb5-1-7/src/kadmin/server/network.c new file mode 100644 index 000000000..df3f01cf0 --- /dev/null +++ b/krb5-1-7/src/kadmin/server/network.c @@ -0,0 +1,2039 @@ +/* + * kadmin/server/network.c + * + * Copyright 1990,2000,2007,2008,2009 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 kadmin server (based on KDC code). + */ + +#include "k5-int.h" +#include "com_err.h" +#include "kadm5/admin.h" +#include "kadm5/server_internal.h" +#include "kadm5/kadm_rpc.h" +#include "iprop.h" +#include "adm_proto.h" +#include "misc.h" +#include +#include + +#include +#include +#include "port-sockets.h" +#include "socket-utils.h" + +#ifdef HAVE_NETINET_IN_H +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +/* for SIOCGIFCONF, etc. */ +#include +#endif +#include +#if HAVE_SYS_SELECT_H +#include +#endif +#include + +#ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */ +#include +#endif + +#ifdef HAVE_SYS_FILIO_H +#include /* FIONBIO */ +#endif + +#include "fake-addrinfo.h" + +/* XXX */ +#define KDC5_NONET (-1779992062L) + +/* 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 + +/* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to + IPV6_PKTINFO for RFC 2292 implementations. */ +#ifndef IPV6_RECVPKTINFO +#define IPV6_RECVPKTINFO IPV6_PKTINFO +#endif +/* Parallel, though not standardized. */ +#ifndef IP_RECVPKTINFO +#define IP_RECVPKTINFO IP_PKTINFO +#endif + +static int +set_pktinfo(int sock, int family) +{ + int sockopt = 1; + int option = 0, proto = 0; + + switch (family) { +#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO) + case AF_INET: + proto = IPPROTO_IP; + option = IP_RECVPKTINFO; + break; +#endif +#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) + case AF_INET6: + proto = IPPROTO_IPV6; + option = IPV6_RECVPKTINFO; + break; +#endif + default: + return EINVAL; + } + if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt))) + return errno; + return 0; +} + + +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)) + strlcpy(buf, "", sizeof(buf)); + 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; +} + +/* kadmin data. */ + +enum conn_type { + CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP, + CONN_RPC_LISTENER, CONN_RPC, + CONN_ROUTING +}; + +/* Per-connection info. */ +struct connection { + int fd; + enum conn_type type; + void (*service)(void *handle, struct connection *, const char *, int); + union { + /* Type-specific information. */ + 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; + struct { + SVCXPRT *transp; + } rpc; + } 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) \ + (free(set.data), set.data = 0, set.max = 0, set.n = 0) + + +/* Set connections; */ +static SET(struct connection *) connections; +#define n_sockets connections.n +#define conns connections.data + +/* Set udp_port_data, tcp_port_data; */ +static SET(u_short) udp_port_data, tcp_port_data; + +struct rpc_svc_data { + u_short port; + u_long prognum; + u_long versnum; + void (*dispatch)(); +}; + +static SET(struct rpc_svc_data) rpc_svc_data; + +#include "cm.h" + +static struct select_state sstate; +static fd_set rpc_listenfds; + +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; +} + +static krb5_error_code add_rpc_service(int port, u_long prognum, u_long versnum, + void (*dispatch)()) +{ + int i; + void *tmp; + struct rpc_svc_data svc, val; + + svc.port = port; + if (svc.port != port) + return EINVAL; + svc.prognum = prognum; + svc.versnum = versnum; + svc.dispatch = dispatch; + + FOREACH_ELT (rpc_svc_data, i, val) { + if (val.port == port) + return 0; + } + if (!ADD(rpc_svc_data, svc, 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; + int udp_flags; +#define UDP_DO_IPV4 1 +#define UDP_DO_IPV6 2 +}; + +static struct connection * +add_fd (struct socksetup *data, int sock, enum conn_type conntype, + void (*service)(void *handle, struct connection *, const char *, int)) +{ + struct connection *newconn; + void *tmp; + +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + data->retval = EMFILE; /* XXX */ + com_err(data->prog, 0, + "file descriptor number %d too high", sock); + return 0; + } +#endif + newconn = (struct connection *)malloc(sizeof(*newconn)); + if (newconn == NULL) { + data->retval = ENOMEM; + com_err(data->prog, ENOMEM, + "cannot allocate storage for connection info"); + return 0; + } + if (!ADD(connections, newconn, tmp)) { + data->retval = ENOMEM; + com_err(data->prog, ENOMEM, "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(void *handle, struct connection *, const char *, int); +static void accept_tcp_connection(void *handle, struct connection *, const char *, int); +static void process_tcp_connection(void *handle, struct connection *, const char *, int); +static void accept_rpc_connection(void *handle, struct connection *, const char *, int); +static void process_rpc_connection(void *handle, struct connection *, const char *, int); + +static struct connection * +add_udp_fd (struct socksetup *data, int sock, int pktinfo) +{ + return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : 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 struct connection * +add_rpc_listener_fd (struct socksetup *data, struct rpc_svc_data *svc, int sock) +{ + struct connection *conn; + + conn = add_fd(data, sock, CONN_RPC_LISTENER, accept_rpc_connection); + if (conn == NULL) + return NULL; + + conn->u.rpc.transp = svctcp_create(sock, 0, 0); + if (conn->u.rpc.transp == NULL) { + krb5_klog_syslog(LOG_ERR, "Cannot create RPC service: %s; continuing", + strerror(errno)); + delete_fd(conn); + return NULL; + } + + if (!svc_register(conn->u.rpc.transp, svc->prognum, svc->versnum, + svc->dispatch, 0)) { + krb5_klog_syslog(LOG_ERR, "Cannot register RPC service: %s; continuing", + strerror(errno)); + delete_fd(conn); + return NULL; + } + + return conn; +} + +static struct connection * +add_rpc_data_fd (struct socksetup *data, int sock) +{ + return add_fd(data, sock, CONN_RPC, process_rpc_connection); +} + +static const int one = 1; + +static int +setnbio(int sock) +{ + return ioctlsocket(sock, FIONBIO, (const void *)&one); +} + +static int +setkeepalive(int sock) +{ + return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(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; + } + set_cloexec_fd(sock); +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + close(sock); + com_err(data->prog, 0, "TCP socket fd number %d (for %s) too high", + sock, paddr(addr)); + return -1; + } +#endif + 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(%d,IPV6_V6ONLY,1) failed", + sock); + else + com_err(data->prog, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", + sock); +#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; +} + +/* Returns -1 or socket fd. */ +static int +setup_a_rpc_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 RPC server socket on %s", + paddr(addr)); + return -1; + } + set_cloexec_fd(sock); +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + close(sock); + com_err(data->prog, 0, "RPC socket fd number %d (for %s) too high", + sock, paddr(addr)); + return -1; + } +#endif + if (setreuseaddr(sock, 1) < 0) + com_err(data->prog, errno, + "Cannot enable SO_REUSEADDR on fd %d", sock); + if (bind(sock, addr, socklen(addr)) == -1) { + com_err(data->prog, errno, + "Cannot bind RPC server 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) { + if (add_tcp_listener_fd(data, s4) == NULL) + close(s4); + else { + FD_SET(s4, &sstate.rfds); + if (s4 >= sstate.max) + sstate.max = s4 + 1; + krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", + s4, paddr((struct sockaddr *)&sin4)); + } + } +#ifdef KRB5_USE_INET6 + if (s6 >= 0) { + if (add_tcp_listener_fd(data, s6) == NULL) { + close(s6); + s6 = -1; + } else { + FD_SET(s6, &sstate.rfds); + if (s6 >= sstate.max) + sstate.max = s6 + 1; + 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_rpc_listener_ports(struct socksetup *data) +{ + struct sockaddr_in sin4; + int i; + struct rpc_svc_data svc; + + 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; + + FOREACH_ELT (rpc_svc_data, i, svc) { + int s4; + + set_sa_port((struct sockaddr *)&sin4, htons(svc.port)); + s4 = setup_a_rpc_listener(data, (struct sockaddr *)&sin4); + if (s4 < 0) + return -1; + else { + if (add_rpc_listener_fd(data, &svc, s4) == NULL) + close(s4); + else { + FD_SET(s4, &sstate.rfds); + if (s4 >= sstate.max) + sstate.max = s4 + 1; + krb5_klog_syslog(LOG_INFO, "listening on fd %d: rpc %s", + s4, paddr((struct sockaddr *)&sin4)); + } + } + } + FD_ZERO(&rpc_listenfds); + rpc_listenfds = svc_fdset; + return 0; +} + +#if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)) +union pktinfo { +#ifdef HAVE_STRUCT_IN6_PKTINFO + struct in6_pktinfo pi6; +#endif +#ifdef HAVE_STRUCT_IN_PKTINFO + struct in_pktinfo pi4; +#endif + char c; +}; + +static int +setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, + char *haddrbuf, int pktinfo); + +static void +setup_udp_pktinfo_ports(struct socksetup *data) +{ +#ifdef IP_PKTINFO + { + struct sockaddr_in sa; + int r; + + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + sa.sin_len = sizeof(sa); +#endif + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV4; + } +#endif +#ifdef IPV6_PKTINFO + { + struct sockaddr_in6 sa; + int r; + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; +#ifdef HAVE_SA_LEN + sa.sin6_len = sizeof(sa); +#endif + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV6; + } +#endif +} +#else /* no pktinfo compile-time support */ +static void +setup_udp_pktinfo_ports(struct socksetup *data) +{ +} +#endif + +static int +setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, + char *haddrbuf, int pktinfo) +{ + int sock = -1, i, r; + u_short port; + + 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_cloexec_fd(sock); +#ifdef KRB5_USE_INET6 + if (addr->sa_family == AF_INET6) { +#ifdef IPV6_V6ONLY + if (setv6only(sock, 1)) + com_err(data->prog, errno, + "setsockopt(%d,IPV6_V6ONLY,1) failed", sock); + else + com_err(data->prog, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", + sock); +#else + krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); +#endif /* IPV6_V6ONLY */ + } +#endif + 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); + close(sock); + return 1; + } +#if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))) + assert(pktinfo == 0); +#endif + if (pktinfo) { + r = set_pktinfo(sock, addr->sa_family); + if (r) { + com_err(data->prog, r, + "Cannot request packet info for udp socket address %s port %d", + haddrbuf, port); + close(sock); + return 1; + } + } + krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock, + paddr((struct sockaddr *)addr), + pktinfo ? " (pktinfo)" : ""); + if (add_udp_fd (data, sock, pktinfo) == 0) { + close(sock); + return 1; + } + FD_SET (sock, &sstate.rfds); + if (sock >= sstate.max) + sstate.max = sock + 1; + } + return 0; +} + +static int +setup_udp_port(void *P_data, struct sockaddr *addr) +{ + struct socksetup *data = P_data; + char haddrbuf[NI_MAXHOST]; + int err; + + if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4)) + return 0; +#ifdef AF_INET6 + if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6)) + return 0; +#endif + err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf), + 0, 0, NI_NUMERICHOST); + if (err) + strlcpy(haddrbuf, "", sizeof(haddrbuf)); + + 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 +#ifdef AF_APPLETALK + case AF_APPLETALK: + return 0; +#endif + default: + krb5_klog_syslog (LOG_INFO, + "skipping unrecognized local address family %d", + addr->sa_family); + return 0; + } + return setup_udp_port_1(data, addr, haddrbuf, 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 + +static int network_reconfiguration_needed = 0; + +#ifdef HAVE_STRUCT_RT_MSGHDR +#include + +static char *rtm_type_name(int type) +{ + switch (type) { + case RTM_ADD: return "RTM_ADD"; + case RTM_DELETE: return "RTM_DELETE"; + case RTM_NEWADDR: return "RTM_NEWADDR"; + case RTM_DELADDR: return "RTM_DELADDR"; + case RTM_IFINFO: return "RTM_IFINFO"; + case RTM_OLDADD: return "RTM_OLDADD"; + case RTM_OLDDEL: return "RTM_OLDDEL"; + case RTM_RESOLVE: return "RTM_RESOLVE"; +#ifdef RTM_NEWMADDR + case RTM_NEWMADDR: return "RTM_NEWMADDR"; + case RTM_DELMADDR: return "RTM_DELMADDR"; +#endif + case RTM_MISS: return "RTM_MISS"; + case RTM_REDIRECT: return "RTM_REDIRECT"; + case RTM_LOSING: return "RTM_LOSING"; + case RTM_GET: return "RTM_GET"; + default: return "?"; + } +} + +static void process_routing_update(void *handle, struct connection *conn, + const char *prog, int selflags) +{ + int n_read; + struct rt_msghdr rtm; + + krb5_klog_syslog(LOG_INFO, "routing socket readable"); + while ((n_read = read(conn->fd, &rtm, sizeof(rtm))) > 0) { + if (n_read < sizeof(rtm)) { + /* Quick hack to figure out if the interesting + fields are present in a short read. + + A short read seems to be normal for some message types. + Only complain if we don't have the critical initial + header fields. */ +#define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD)) + if (n_read < RS(rtm_type) || + n_read < RS(rtm_version) || + n_read < RS(rtm_msglen)) { + krb5_klog_syslog(LOG_ERR, + "short read (%d/%d) from routing socket", + n_read, (int) sizeof(rtm)); + return; + } + } + krb5_klog_syslog(LOG_INFO, + "got routing msg type %d(%s) v%d", + rtm.rtm_type, rtm_type_name(rtm.rtm_type), + rtm.rtm_version); + if (rtm.rtm_msglen > sizeof(rtm)) { + /* It appears we get a partial message and the rest is + thrown away? */ + } else if (rtm.rtm_msglen != n_read) { + krb5_klog_syslog(LOG_ERR, + "read %d from routing socket but msglen is %d", + n_read, rtm.rtm_msglen); + } + switch (rtm.rtm_type) { + case RTM_ADD: + case RTM_DELETE: + case RTM_NEWADDR: + case RTM_DELADDR: + case RTM_IFINFO: + case RTM_OLDADD: + case RTM_OLDDEL: + krb5_klog_syslog(LOG_INFO, "reconfiguration needed"); + network_reconfiguration_needed = 1; + break; + case RTM_RESOLVE: +#ifdef RTM_NEWMADDR + case RTM_NEWMADDR: + case RTM_DELMADDR: +#endif + case RTM_MISS: + case RTM_REDIRECT: + case RTM_LOSING: + case RTM_GET: + /* Not interesting. */ + krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting"); + break; + default: + krb5_klog_syslog(LOG_INFO, "unhandled routing message type, will reconfigure just for the fun of it"); + network_reconfiguration_needed = 1; + break; + } + } +} + +static void +setup_routing_socket(struct socksetup *data) +{ + int sock = socket(PF_ROUTE, SOCK_RAW, 0); + if (sock < 0) { + int e = errno; + krb5_klog_syslog(LOG_INFO, "couldn't set up routing socket: %s", + strerror(e)); + } else { + krb5_klog_syslog(LOG_INFO, "routing socket is fd %d", sock); + add_fd(data, sock, CONN_ROUTING, process_routing_update); + setnbio(sock); + FD_SET(sock, &sstate.rfds); + } +} +#endif + +/* XXX */ +extern int krb5int_debug_sendto_kdc; +extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t); + +krb5_error_code +setup_network(void *handle, const char *prog) +{ + struct socksetup setup_data; + krb5_error_code retval; + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + + 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; + + retval = add_udp_port(server_handle->params.kpasswd_port); + if (retval) + return retval; + + retval = add_tcp_port(server_handle->params.kpasswd_port); + if (retval) + return retval; + + retval = add_rpc_service(server_handle->params.kadmind_port, + KADM, KADMVERS, + kadm_1); + if (retval) + return retval; + +#ifndef DISABLE_IPROP + if (server_handle->params.iprop_enabled) { + retval = add_rpc_service(server_handle->params.iprop_port, + KRB5_IPROP_PROG, KRB5_IPROP_VERS, + krb5_iprop_prog_1); + if (retval) + return retval; + } +#endif /* DISABLE_IPROP */ + + setup_data.prog = prog; + setup_data.retval = 0; + krb5_klog_syslog (LOG_INFO, "setting up network..."); +#ifdef HAVE_STRUCT_RT_MSGHDR + setup_routing_socket(&setup_data); +#endif + /* 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. */ + setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6; + setup_udp_pktinfo_ports(&setup_data); + if (setup_data.udp_flags) { + if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) { + return setup_data.retval; + } + } + setup_tcp_listener_ports(&setup_data); + setup_rpc_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 int +recv_from_to(int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen, + struct sockaddr *to, socklen_t *tolen) +{ +#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) + if (to && tolen) { + /* Clobber with something recognizeable in case we try to use + the address. */ + memset(to, 0x40, *tolen); + *tolen = 0; + } + + return recvfrom(s, buf, len, flags, from, fromlen); +#else + int r; + struct iovec iov; + char cmsg[CMSG_SPACE(sizeof(union pktinfo))]; + struct cmsghdr *cmsgptr; + struct msghdr msg; + + if (!to || !tolen) + return recvfrom(s, buf, len, flags, from, fromlen); + + /* Clobber with something recognizeable in case we can't extract + the address but try to use it anyways. */ + memset(to, 0x40, *tolen); + + iov.iov_base = buf; + iov.iov_len = len; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = from; + msg.msg_namelen = *fromlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof(cmsg); + + r = recvmsg(s, &msg, flags); + if (r < 0) + return r; + *fromlen = msg.msg_namelen; + + /* On Darwin (and presumably all *BSD with KAME stacks), + CMSG_FIRSTHDR doesn't check for a non-zero controllen. RFC + 3542 recommends making this check, even though the (new) spec + for CMSG_FIRSTHDR says it's supposed to do the check. */ + if (msg.msg_controllen) { + cmsgptr = CMSG_FIRSTHDR(&msg); + while (cmsgptr) { +#ifdef IP_PKTINFO + if (cmsgptr->cmsg_level == IPPROTO_IP + && cmsgptr->cmsg_type == IP_PKTINFO + && *tolen >= sizeof(struct sockaddr_in)) { + struct in_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in)); + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; + ((struct sockaddr_in *)to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return r; + } +#endif +#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)&& defined(HAVE_STRUCT_IN6_PKTINFO) + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO + && *tolen >= sizeof(struct sockaddr_in6)) { + struct in6_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in6)); + pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr; + ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6; + *tolen = sizeof(struct sockaddr_in6); + return r; + } +#endif + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr); + } + } + /* No info about destination addr was available. */ + *tolen = 0; + return r; +#endif +} + +static int +send_to_from(int s, void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen, + const struct sockaddr *from, socklen_t fromlen) +{ +#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) + return sendto(s, buf, len, flags, to, tolen); +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsgptr; + char cbuf[CMSG_SPACE(sizeof(union pktinfo))]; + + if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) { + use_sendto: + return sendto(s, buf, len, flags, to, tolen); + } + + iov.iov_base = buf; + iov.iov_len = len; + /* Truncation? */ + if (iov.iov_len != len) + return EINVAL; + memset(cbuf, 0, sizeof(cbuf)); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *) to; + msg.msg_namelen = tolen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cbuf; + /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL + on Linux. */ + msg.msg_controllen = sizeof(cbuf); + cmsgptr = CMSG_FIRSTHDR(&msg); + msg.msg_controllen = 0; + + switch (from->sa_family) { +#if defined(IP_PKTINFO) + case AF_INET: + if (fromlen != sizeof(struct sockaddr_in)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + { + struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in *from4 = (const struct sockaddr_in *)from; + p->ipi_spec_dst = from4->sin_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + break; +#endif +#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) + case AF_INET6: + if (fromlen != sizeof(struct sockaddr_in6)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + { + struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from; + p->ipi6_addr = from6->sin6_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + break; +#endif + default: + goto use_sendto; + } + return sendmsg(s, &msg, flags); +#endif +} + +/* Dispatch routine for set/change password */ +static krb5_error_code +dispatch(void *handle, + struct sockaddr *local_saddr, krb5_fulladdr *remote_faddr, + krb5_data *request, krb5_data **response) +{ + krb5_error_code ret; + krb5_keytab kt = NULL; + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + krb5_fulladdr local_faddr; + krb5_address **local_kaddrs = NULL, local_kaddr_buf; + + *response = NULL; + + if (local_saddr == NULL) { + ret = krb5_os_localaddr(server_handle->context, &local_kaddrs); + if (ret != 0) + goto cleanup; + + local_faddr.address = local_kaddrs[0]; + local_faddr.port = 0; + } else { + local_faddr.address = &local_kaddr_buf; + init_addr(&local_faddr, local_saddr); + } + + ret = krb5_kt_resolve(server_handle->context, "KDB:", &kt); + if (ret != 0) { + krb5_klog_syslog(LOG_ERR, "chpw: Couldn't open admin keytab %s", + krb5_get_error_message(server_handle->context, ret)); + goto cleanup; + } + + *response = (krb5_data *)malloc(sizeof(krb5_data)); + if (*response == NULL) { + ret = ENOMEM; + goto cleanup; + } + + ret = process_chpw_request(server_handle->context, + handle, + server_handle->params.realm, + kt, + &local_faddr, + remote_faddr, + request, + *response); + +cleanup: + if (local_kaddrs != NULL) + krb5_free_addresses(server_handle->context, local_kaddrs); + + krb5_kt_close(server_handle->context, kt); + + return ret; +} + +static void process_packet(void *handle, + struct connection *conn, const char *prog, + int selflags) +{ + int cc; + socklen_t saddr_len, daddr_len; + krb5_fulladdr faddr; + krb5_error_code retval; + struct sockaddr_storage saddr, daddr; + krb5_address addr; + krb5_data request; + krb5_data *response; + char pktbuf[MAX_DGRAM_SIZE]; + int port_fd = conn->fd; + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + + response = NULL; + saddr_len = sizeof(saddr); + daddr_len = sizeof(daddr); + cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0, + (struct sockaddr *)&saddr, &saddr_len, + (struct sockaddr *)&daddr, &daddr_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? */ + +#if 0 + if (daddr_len > 0) { + char addrbuf[100]; + if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf), + 0, 0, NI_NUMERICHOST)) + strlcpy(addrbuf, "?", sizeof(addrbuf)); + com_err(prog, 0, "pktinfo says local addr is %s", addrbuf); + } +#endif + + if (daddr_len == 0 && conn->type == CONN_UDP) { + /* If the PKTINFO option isn't set, this socket should be + bound to a specific local address. This info probably + should've been saved in our socket data structure at setup + time. */ + daddr_len = sizeof(daddr); + if (getsockname(port_fd, (struct sockaddr *)&daddr, &daddr_len) != 0) + daddr_len = 0; + /* On failure, keep going anyways. */ + } + + request.length = cc; + request.data = pktbuf; + faddr.address = &addr; + init_addr(&faddr, ss2sa(&saddr)); + /* this address is in net order */ + if ((retval = dispatch(handle, ss2sa(&daddr), &faddr, &request, &response))) { + com_err(prog, retval, "while dispatching (udp)"); + return; + } + if (response == NULL) + return; + cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0, + (struct sockaddr *)&saddr, saddr_len, + (struct sockaddr *)&daddr, daddr_len); + if (cc == -1) { + char addrbuf[46]; + krb5_free_data(server_handle->context, response); + if (inet_ntop(((struct sockaddr *)&saddr)->sa_family, + addr.contents, addrbuf, sizeof(addrbuf)) == 0) { + strlcpy(addrbuf, "?", sizeof(addrbuf)); + } + com_err(prog, errno, "while sending reply to %s/%d", + addrbuf, faddr.port); + return; + } + if (cc != response->length) { + com_err(prog, 0, "short reply write %d vs %d\n", + response->length, cc); + } + krb5_free_data(server_handle->context, response); + return; +} + +static int tcp_or_rpc_data_counter; +static int max_tcp_or_rpc_data_connections = 45; + +static void kill_tcp_or_rpc_connection(void *, struct connection *, int isForcedClose); + +static int kill_lru_tcp_or_rpc_connection(void *handle, struct connection *newconn) +{ + struct connection *oldest_tcp = NULL; + struct connection *c; + int i, fd = -1; + + krb5_klog_syslog(LOG_INFO, "too many connections"); + + FOREACH_ELT (connections, i, c) { + if (c->type != CONN_TCP && c->type != CONN_RPC) + 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 %s fd %d from %s", + c->type == CONN_RPC ? "rpc" : "tcp", + oldest_tcp->fd, oldest_tcp->u.tcp.addrbuf); + fd = oldest_tcp->fd; + kill_tcp_or_rpc_connection(handle, oldest_tcp, 1); + } + return fd; +} + +static void accept_tcp_connection(void *handle, + 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; + set_cloexec_fd(s); +#ifndef _WIN32 + if (s >= FD_SETSIZE) { + close(s); + return; + } +#endif + setnbio(s), setnolinger(s), setkeepalive(s); + + sockdata.prog = prog; + sockdata.retval = 0; + + newconn = add_tcp_data_fd(&sockdata, s); + if (newconn == NULL) + return; + + if (getnameinfo((struct sockaddr *)&addr_s, addrlen, + newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(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++ = '.'; + strlcpy(p, tmpbuf, end - p); + } + } +#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_or_rpc_data_counter > max_tcp_or_rpc_data_connections) + kill_lru_tcp_or_rpc_connection(handle, newconn); + + 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_or_rpc_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_or_rpc_connection(void *handle, struct connection *conn, int isForcedClose) +{ + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + + assert(conn->type == CONN_TCP || conn->type == CONN_RPC); + assert(conn->fd != -1); + + if (conn->u.tcp.response) + krb5_free_data(server_handle->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--; + + /* In the non-forced case, the RPC runtime will close the descriptor for us */ + if (conn->type == CONN_TCP || isForcedClose) { + close(conn->fd); + } + + /* For RPC connections, call into RPC runtime to flush out any internal state */ + if (conn->type == CONN_RPC && isForcedClose) { + fd_set fds; + + FD_ZERO(&fds); + FD_SET(conn->fd, &fds); + + svc_getreqset(&fds); + + if (FD_ISSET(conn->fd, &svc_fdset)) { + krb5_klog_syslog(LOG_ERR, + "descriptor %d closed but still in svc_fdset", conn->fd); + } + } + + conn->fd = -1; + delete_fd(conn); + tcp_or_rpc_data_counter--; +} + +static krb5_error_code +make_toolong_error (void *handle, krb5_data **out) +{ + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + + retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec); + if (retval) + return retval; + errpkt.error = KRB_ERR_FIELD_TOOLONG; + retval = krb5_build_principal(server_handle->context, &errpkt.server, + strlen(server_handle->params.realm), + server_handle->params.realm, + "kadmin", "changepw", NULL); + if (retval) + return retval; + 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(server_handle->context, &errpkt, scratch); + if (retval) { + free(scratch); + return retval; + } + + *out = scratch; + return 0; +} + +static void +queue_tcp_outgoing_response(struct connection *conn) +{ + store_32_be(conn->u.tcp.response->length, conn->u.tcp.lenbuf); + 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_SET(conn->fd, &sstate.wfds); +} + +static void +process_tcp_connection(void *handle, + struct connection *conn, const char *prog, int selflags) +{ + int isForcedClose = 1; /* not used now, but for completeness */ + + 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 */ + isForcedClose = 0; + 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. */ + isForcedClose = 0; + 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 = load_32_be(p); + 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 (handle, &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; + struct sockaddr_storage local_saddr; + socklen_t local_saddrlen = sizeof(local_saddr); + struct sockaddr *local_saddrp = NULL; + + 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; + + if (getsockname(conn->fd, ss2sa(&local_saddr), &local_saddrlen) == 0) { + local_saddrp = ss2sa(&local_saddr); + } + + err = dispatch(handle, local_saddrp, &conn->u.tcp.faddr, + &request, &conn->u.tcp.response); + if (err) { + com_err(prog, err, "while dispatching (tcp)"); + goto kill_tcp_connection; + } + have_response: + queue_tcp_outgoing_response(conn); + FD_CLR(conn->fd, &sstate.rfds); + } + } else + abort(); + + return; + +kill_tcp_connection: + kill_tcp_or_rpc_connection(handle, conn, isForcedClose); +} + +static void service_conn(void *handle, + struct connection *conn, const char *prog, + int selflags) +{ + conn->service(handle, conn, prog, selflags); +} + +static int getcurtime(struct timeval *tvp) +{ +#ifdef _WIN32 + struct _timeb tb; + _ftime(&tb); + tvp->tv_sec = tb.time; + tvp->tv_usec = tb.millitm * 1000; + return 0; +#else + return gettimeofday(tvp, 0) ? errno : 0; +#endif +} + +krb5_error_code +listen_and_process(void *handle, 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, netchanged = 0; + krb5_error_code err; + kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; + + if (conns == (struct connection **) NULL) + return KDC5_NONET; + + while (!signal_request_exit) { + if (signal_request_hup) { + krb5_klog_reopen(server_handle->context); + reset_db(); + signal_request_hup = 0; + } +#ifdef PURIFY + if (signal_pure_report) { + purify_new_reports(); + signal_pure_report = 0; + } + if (signal_pure_clear) { + purify_clear_new_reports(); + signal_pure_clear = 0; + } +#endif /* PURIFY */ + if (network_reconfiguration_needed) { + krb5_klog_syslog(LOG_INFO, "network reconfiguration needed"); + /* It might be tidier to add a timer-callback interface to + the control loop here, but for this one use, it's not a + big deal. */ + err = getcurtime(&sstate.end_time); + if (err) { + com_err(prog, err, "while getting the time"); + continue; + } + sstate.end_time.tv_sec += 3; + netchanged = 1; + } else + sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0; + + err = krb5int_cm_call_select(&sstate, &sout, &sret); + if (err) { + if (err != EINTR) + com_err(prog, err, "while selecting for network input(1)"); + continue; + } + if (sret == 0 && netchanged) { + network_reconfiguration_needed = 0; + closedown_network(handle, prog); + err = setup_network(handle, prog); + if (err) { + com_err(prog, err, "while reinitializing network"); + return err; + } + netchanged = 0; + } + if (sret == -1) { + if (errno != EINTR) + com_err(prog, errno, "while selecting for network input(2)"); + continue; + } + nfound = sret; + for (i=0; i 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(handle, conns[i], prog, sflags); + } + } + krb5_klog_syslog(LOG_INFO, "shutdown signal received"); + return 0; +} + +krb5_error_code +closedown_network(void *handle, 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) { + krb5_klog_syslog(LOG_INFO, "closing down fd %d", conn->fd); + (void) close(conn->fd); + if (conn->type == CONN_RPC) { + fd_set fds; + + FD_ZERO(&fds); + FD_SET(conn->fd, &fds); + + svc_getreqset(&fds); + } + } + if (conn->type == CONN_RPC_LISTENER) { + if (conn->u.rpc.transp != NULL) + svc_destroy(conn->u.rpc.transp); + } + 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); + FREE_SET_DATA(rpc_svc_data); + + return 0; +} + +static void accept_rpc_connection(void *handle, struct connection *conn, + const char *prog, int selflags) +{ + struct socksetup sockdata; + fd_set fds; + register int s; + + assert(selflags & SSF_READ); + + if ((selflags & SSF_READ) == 0) + return; + + sockdata.prog = prog; + sockdata.retval = 0; + + /* + * Service the woken RPC listener descriptor. + */ + FD_ZERO(&fds); + FD_SET(conn->fd, &fds); + + svc_getreqset(&fds); + + /* + * Scan svc_fdset for any new connections. + */ + for (s = 0; s < FD_SETSIZE; s++) { + /* sstate.rfds |= svc_fdset & ~(rpc_listenfds | sstate.rfds) */ + if (FD_ISSET(s, &svc_fdset) + && !FD_ISSET(s, &rpc_listenfds) + && !FD_ISSET(s, &sstate.rfds)) + { + struct connection *newconn; + struct sockaddr_storage addr_s; + struct sockaddr *addr = (struct sockaddr *)&addr_s; + socklen_t addrlen = sizeof(addr_s); + char tmpbuf[10]; + + newconn = add_rpc_data_fd(&sockdata, s); + if (newconn == NULL) + continue; + + set_cloexec_fd(s); +#if 0 + setnbio(s), setnolinger(s), setkeepalive(s); +#endif + + if (getpeername(s, addr, &addrlen) || + getnameinfo(addr, addrlen, + newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(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++ = '.'; + strlcpy(p, tmpbuf, end - p); + } + } +#if 0 + krb5_klog_syslog(LOG_INFO, "accepted RPC 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.start_time = time(0); + + if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) + kill_lru_tcp_or_rpc_connection(handle, newconn); + + newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr; + init_addr(&newconn->u.tcp.faddr, ss2sa(&newconn->u.tcp.addr_s)); + + FD_SET(s, &sstate.rfds); + if (sstate.max <= s) + sstate.max = s + 1; + } + } +} + +static void process_rpc_connection(void *handle, struct connection *conn, + const char *prog, int selflags) +{ + fd_set fds; + + assert(selflags & SSF_READ); + + if ((selflags & SSF_READ) == 0) + return; + + FD_ZERO(&fds); + FD_SET(conn->fd, &fds); + + svc_getreqset(&fds); + + if (!FD_ISSET(conn->fd, &svc_fdset)) + kill_tcp_or_rpc_connection(handle, conn, 0); +} + +#endif /* INET */ diff --git a/krb5-1-7/src/kadmin/server/ovsec_kadmd.c b/krb5-1-7/src/kadmin/server/ovsec_kadmd.c new file mode 100644 index 000000000..6578e623d --- /dev/null +++ b/krb5-1-7/src/kadmin/server/ovsec_kadmd.c @@ -0,0 +1,1056 @@ +/* + * 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 +#include +#include +#include +#ifdef _AIX +#include +#endif +#include +#include +#include +#include +#include /* inet_ntoa */ +#include +#include +#include +#include "gssapiP_krb5.h" /* for kg_get_context */ +#include +#include +#include +#include +#include +#include "kdb_kt.h" /* for krb5_ktkdb_set_context */ +#include +#include "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */ +#include + +#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(iprop_role iproprole); +void request_exit(int); +void request_hup(int); +void reset_db(void); +void sig_pipe(int); + +#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 , + * 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; +extern krb5_keylist_node *master_keylist; + +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); + +#ifndef DISABLE_IPROP +int ipropfd; +#endif + +#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 : " 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 nofork = 0; + +int main(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind, opterr; + int ret, oldnames = 0; + OM_uint32 OMret, major_status, minor_status; + char *whoami; + gss_buffer_desc in_buf; + 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; + int i; + int strong_random = 1; + + kdb_log_context *log_ctx; + + 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 if (strcmp(*argv, "-W") == 0) { + strong_random = 0; + } 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 ((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 " + "(%lx) 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); + } + + if ((ret = setup_network(global_server_handle, whoami))) { + const char *e_txt = krb5_get_error_message (context, ret); + krb5_klog_syslog(LOG_ERR, "%s: %s while initializing network, aborting", + whoami, e_txt); + fprintf(stderr, "%s: %s while initializing network, aborting\n", + whoami, e_txt); + 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_db_set_mkey_list(hctx, master_keylist); + if (ret) { + krb5_klog_syslog(LOG_ERR, "Can't set master key list 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, strong_random, 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); + } + + if (params.iprop_enabled == TRUE) + ulog_set_role(hctx, IPROP_MASTER); + else + ulog_set_role(hctx, IPROP_NULL); + + log_ctx = hctx->kdblog_context; + + if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { + /* + * IProp is enabled, so let's map in the update log + * and setup the service. + */ + if ((ret = ulog_map(hctx, params.iprop_logfile, + params.iprop_ulogsize, FKADMIND, db_args)) != 0) { + fprintf(stderr, + _("%s: %s while mapping update log (`%s.ulog')\n"), + whoami, error_message(ret), params.dbname); + krb5_klog_syslog(LOG_ERR, + _("%s while mapping update log (`%s.ulog')"), + error_message(ret), params.dbname); + krb5_klog_close(context); + exit(1); + } + + + if (nofork) + fprintf(stderr, + "%s: create IPROP svc (PROG=%d, VERS=%d)\n", + whoami, KRB5_IPROP_PROG, KRB5_IPROP_VERS); + +#if 0 + if (!svc_create(krb5_iprop_prog_1, + KRB5_IPROP_PROG, KRB5_IPROP_VERS, + "circuit_v")) { + fprintf(stderr, + _("%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n"), + whoami, + KRB5_IPROP_PROG, KRB5_IPROP_VERS); + krb5_klog_syslog(LOG_ERR, + _("Cannot create IProp RPC service (PROG=%d, VERS=%d), failing."), + KRB5_IPROP_PROG, KRB5_IPROP_VERS); + krb5_klog_close(context); + exit(1); + } +#endif + +#if 0 /* authgss only? */ + if ((ret = kiprop_get_adm_host_srv_name(context, + params.realm, + &kiprop_name)) != 0) { + krb5_klog_syslog(LOG_ERR, + _("%s while getting IProp svc name, failing"), + error_message(ret)); + fprintf(stderr, + _("%s: %s while getting IProp svc name, failing\n"), + whoami, error_message(ret)); + krb5_klog_close(context); + exit(1); + } + + auth_gssapi_name iprop_name; + iprop_name.name = build_princ_name(foo, bar); + if (iprop_name.name == NULL) { + foo error; + } + iprop_name.type = nt_krb5_name_oid; + if (svcauth_gssapi_set_names(&iprop_name, 1) == FALSE) { + foo error; + } + if (!rpc_gss_set_svc_name(kiprop_name, "kerberos_v5", 0, + KRB5_IPROP_PROG, KRB5_IPROP_VERS)) { + rpc_gss_error_t err; + (void) rpc_gss_get_error(&err); + + krb5_klog_syslog(LOG_ERR, + _("Unable to set RPCSEC_GSS service name (`%s'), failing."), + kiprop_name ? kiprop_name : ""); + + fprintf(stderr, + _("%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n"), + whoami, + kiprop_name ? kiprop_name : ""); + + if (nofork) { + fprintf(stderr, + "%s: set svc name (rpcsec err=%d, sys err=%d)\n", + whoami, + err.rpc_gss_error, + err.system_error); + } + + exit(1); + } + free(kiprop_name); +#endif + } + + setup_signal_handlers(log_ctx->iproprole); + krb5_klog_syslog(LOG_INFO, _("starting")); + if (nofork) + fprintf(stderr, "%s: starting...\n", whoami); + + listen_and_process(global_server_handle, whoami); + krb5_klog_syslog(LOG_INFO, "finished, exiting"); + + /* Clean up memory, etc */ + svcauth_gssapi_unset_names(); + kadm5_destroy(global_server_handle); + closedown_network(global_server_handle, whoami); + 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(i = 0 ; i < 4; i++) { + if (names[i].name) { + free(names[i].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(iprop_role iproprole) { +#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 */ + + /* + * IProp will fork for a full-resync, we don't want to + * wait on it and we don't want the living dead procs either. + */ + if (iproprole == IPROP_MASTER) { + s_action.sa_handler = SIG_IGN; + (void) sigaction(SIGCHLD, &s_action, (struct sigaction *) NULL); + } +#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 */ + + /* + * IProp will fork for a full-resync, we don't want to + * wait on it and we don't want the living dead procs either. + */ + if (iproprole == IPROP_MASTER) + (void) signal(SIGCHLD, SIG_IGN); +#endif /* POSIX_SIGNALS */ +} + +#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 + * char * pointing to "name@realm" + * + * Requires: + * name be non-null. + * + * Effects: + * Modifies: + */ + +char *build_princ_name(char *name, char *realm) +{ + char *fullname; + + if (realm) { + if (asprintf(&fullname, "%s@%s", name, realm) < 0) + fullname = NULL; + } else + fullname = strdup(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, (int) clen, (char *) client.value, cdots, + (int) slen, (char *) 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, (int) clen, (char *) client.value, cdots, + (int) slen, (char *) 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: , */ + + 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!", (int) msg.length, + (char *) msg.value); + return; + } + + krb5_klog_syslog(LOG_NOTICE, "%s %.*s", m, (int)msg.length, + (char *)msg.value); + (void) gss_release_buffer(&minor_stat, &msg); + + if (!msg_ctx) + break; + } +} + diff --git a/krb5-1-7/src/kadmin/server/schpw.c b/krb5-1-7/src/kadmin/server/schpw.c new file mode 100644 index 000000000..c3b7fa1e3 --- /dev/null +++ b/krb5-1-7/src/kadmin/server/schpw.c @@ -0,0 +1,477 @@ +#include "k5-int.h" +#include +#include +#include /* krb5_klog_syslog */ +#include +#include + +#include "misc.h" + +#ifndef GETSOCKNAME_ARG3_TYPE +#define GETSOCKNAME_ARG3_TYPE int +#endif + +#define RFC3244_VERSION 0xff80 + +krb5_error_code +process_chpw_request(context, server_handle, realm, keytab, + local_faddr, remote_faddr, req, rep) + krb5_context context; + void *server_handle; + char *realm; + krb5_keytab keytab; + krb5_fulladdr *local_faddr; + krb5_fulladdr *remote_faddr; + krb5_data *req; + krb5_data *rep; +{ + krb5_error_code ret; + char *ptr; + int plen, vno; + krb5_data ap_req, ap_rep; + krb5_auth_context auth_context; + krb5_principal changepw; + krb5_principal client, target = NULL; + krb5_ticket *ticket; + krb5_data cipher, clear; + krb5_replay_data replay; + krb5_error krberror; + int numresult; + char strresult[1024]; + char *clientstr = NULL, *targetstr = NULL; + const char *errmsg = NULL; + size_t clen; + char *cdots; + struct sockaddr_storage ss; + socklen_t salen; + char addrbuf[100]; + krb5_address *addr = remote_faddr->address; + + 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; + strlcpy(strresult, "Request was truncated", sizeof(strresult)); + 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 && vno != RFC3244_VERSION) { + ret = KRB5KDC_ERR_BAD_PVNO; + numresult = KRB5_KPASSWD_BAD_VERSION; + snprintf(strresult, sizeof(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; + strlcpy(strresult, "Request was truncated in AP-REQ", + sizeof(strresult)); + 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; + strlcpy(strresult, "Failed initializing auth context", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed initializing auth context", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_build_principal(context, &changepw, strlen(realm), realm, + "kadmin", "changepw", NULL); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed building kadmin/changepw principal", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_rd_req(context, &auth_context, &ap_req, changepw, keytab, + NULL, &ticket); + + if (ret) { + numresult = KRB5_KPASSWD_AUTHERROR; + strlcpy(strresult, "Failed reading application request", + sizeof(strresult)); + goto chpwfail; + } + + /* 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_faddr->address); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed storing client internet address", + sizeof(strresult)); + goto chpwfail; + } + + /* construct the ap-rep */ + + ret = krb5_mk_rep(context, auth_context, &ap_rep); + if (ret) { + numresult = KRB5_KPASSWD_AUTHERROR; + strlcpy(strresult, "Failed replying to application request", + sizeof(strresult)); + goto chpwfail; + } + + /* decrypt the ChangePasswdData */ + + 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; + strlcpy(strresult, "Failed decrypting request", sizeof(strresult)); + goto chpwfail; + } + + client = ticket->enc_part2->client; + + /* decode ChangePasswdData for setpw requests */ + if (vno == RFC3244_VERSION) { + krb5_data *clear_data; + + ret = decode_krb5_setpw_req(&clear, &clear_data, &target); + if (ret != 0) { + numresult = KRB5_KPASSWD_MALFORMED; + strlcpy(strresult, "Failed decoding ChangePasswdData", + sizeof(strresult)); + goto chpwfail; + } + + memset(clear.data, 0, clear.length); + free(clear.data); + + clear = *clear_data; + free(clear_data); + + if (target != NULL) { + ret = krb5_unparse_name(context, target, &targetstr); + if (ret != 0) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed unparsing target name for log", + sizeof(strresult)); + goto chpwfail; + } + } + } + + ret = krb5_unparse_name(context, client, &clientstr); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed unparsing client name for log", + sizeof(strresult)); + goto chpwfail; + } + + /* for cpw, verify that this is an AS_REQ ticket */ + if (vno == 1 && + (ticket->enc_part2->flags & TKT_FLG_INITIAL) == 0) { + numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED; + strlcpy(strresult, "Ticket must be derived from a password", + sizeof(strresult)); + 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, client, target, + (ticket->enc_part2->flags & TKT_FLG_INITIAL) != 0, + ptr, NULL, strresult, sizeof(strresult)); + if (ret) + errmsg = krb5_get_error_message(context, ret); + + /* zap the password */ + memset(clear.data, 0, clear.length); + memset(ptr, 0, clear.length); + free(clear.data); + free(ptr); + clear.length = 0; + + clen = strlen(clientstr); + trunc_name(&clen, &cdots); + + switch (addr->addrtype) { + case ADDRTYPE_INET: { + struct sockaddr_in *sin = ss2sin(&ss); + + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, addr->contents, addr->length); + sin->sin_port = htons(remote_faddr->port); + salen = sizeof(*sin); + break; + } + case ADDRTYPE_INET6: { + struct sockaddr_in6 *sin6 = ss2sin6(&ss); + + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, addr->contents, addr->length); + sin6->sin6_port = htons(remote_faddr->port); + salen = sizeof(*sin6); + break; + } + default: { + struct sockaddr *sa = ss2sa(&ss); + + sa->sa_family = AF_UNSPEC; + salen = sizeof(*sa); + break; + } + } + + if (getnameinfo(ss2sa(&ss), salen, + addrbuf, sizeof(addrbuf), NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV) != 0) + strlcpy(addrbuf, "", sizeof(addrbuf)); + + if (vno == RFC3244_VERSION) { + size_t tlen; + char *tdots; + const char *targetp; + + if (target == NULL) { + tlen = clen; + tdots = cdots; + targetp = targetstr; + } else { + tlen = strlen(targetstr); + trunc_name(&tlen, &tdots); + targetp = clientstr; + } + + krb5_klog_syslog(LOG_NOTICE, "setpw request from %s by %.*s%s for %.*s%s: %s", + addrbuf, + (int) clen, clientstr, cdots, + (int) tlen, targetp, tdots, + errmsg ? errmsg : "success"); + } else { + krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %.*s%s: %s", + addrbuf, + (int) clen, clientstr, cdots, + errmsg ? errmsg : "success"); + } + switch (ret) { + case KADM5_AUTH_CHANGEPW: + numresult = KRB5_KPASSWD_ACCESSDENIED; + break; + case KADM5_PASS_Q_TOOSHORT: + case KADM5_PASS_REUSE: + case KADM5_PASS_Q_CLASS: + case KADM5_PASS_Q_DICT: + case KADM5_PASS_TOOSOON: + numresult = KRB5_KPASSWD_HARDERROR; + break; + case 0: + numresult = KRB5_KPASSWD_SUCCESS; + strlcpy(strresult, "", sizeof(strresult)); + break; + default: + numresult = KRB5_KPASSWD_SOFTERROR; + break; + } + +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_faddr->address, NULL); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, + "Failed storing client and server internet addresses", + sizeof(strresult)); + } else { + ret = krb5_mk_priv(context, auth_context, &clear, &cipher, + &replay); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed encrypting reply", + sizeof(strresult)); + } + } + } + + /* 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) { + free(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); + if (rep->data == NULL) { + rep->length = 0; /* checked by caller */ + ret = ENOMEM; + goto bailout; + } + 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) + free(ap_rep.data); + if (ticket) + krb5_free_ticket(context, ticket); + if (clear.length) + free(clear.data); + if (cipher.length) + free(cipher.data); + if (target) + krb5_free_principal(context, target); + if (targetstr) + krb5_free_unparsed_name(context, targetstr); + if (clientstr) + krb5_free_unparsed_name(context, clientstr); + if (errmsg) + krb5_free_error_message(context, errmsg); + + return(ret); +} diff --git a/krb5-1-7/src/kadmin/server/server_glue_v1.c b/krb5-1-7/src/kadmin/server/server_glue_v1.c new file mode 100644 index 000000000..dfd6430f1 --- /dev/null +++ b/krb5-1-7/src/kadmin/server/server_glue_v1.c @@ -0,0 +1,32 @@ +#define USE_KADM5_API_VERSION 1 +#include +#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-7/src/kadmin/server/server_stubs.c b/krb5-1-7/src/kadmin/server/server_stubs.c new file mode 100644 index 000000000..038a4a73f --- /dev/null +++ b/krb5-1-7/src/kadmin/server/server_stubs.c @@ -0,0 +1,1662 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#include +#include /* for gss_nt_krb5_name */ +#include +#include +#include +#include +#include +#include +#include /* inet_ntoa */ +#include /* krb5_klog_syslog */ +#include "misc.h" +#include + +#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); + +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 + * (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; + + *out_handle = NULL; + + 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) +{ + if (!handle) + return; + 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. + */ +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); + + /* okay to cast lengths to int because trunc_name limits max value */ + return krb5_klog_syslog(LOG_NOTICE, + "Unauthorized request: %s, %.*s%s, " + "client=%.*s%s, service=%.*s%s, addr=%s", + op, (int)tlen, target, tdots, + (int)clen, (char *)client->value, cdots, + (int)slen, (char *)server->value, sdots, + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); +} + +static int +log_done( + char *op, + char *target, + const 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); + + /* okay to cast lengths to int because trunc_name limits max value */ + return krb5_klog_syslog(LOG_NOTICE, + "Request: %s, %.*s%s, %s, " + "client=%.*s%s, service=%.*s%s, addr=%s", + op, (int)tlen, target, tdots, errmsg, + (int)clen, (char *)client->value, cdots, + (int)slen, (char *)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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_create_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); + + exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_create_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); + +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_delete_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); + +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_modify_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + 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))) + 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) { + /* okay to cast lengths to int because trunc_name limits max value */ + krb5_klog_syslog(LOG_NOTICE, + "Unauthorized request: kadm5_rename_principal, " + "%.*s%s to %.*s%s, " + "client=%.*s%s, service=%.*s%s, addr=%s", + (int)tlen1, prime_arg1, tdots1, + (int)tlen2, prime_arg2, tdots2, + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)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 = krb5_get_error_message(handle->context, ret.code); + + /* okay to cast lengths to int because trunc_name limits max value */ + krb5_klog_syslog(LOG_NOTICE, + "Request: kadm5_rename_principal, " + "%.*s%s to %.*s%s, %s, " + "client=%.*s%s, service=%.*s%s, addr=%s", + (int)tlen1, prime_arg1, tdots1, + (int)tlen2, prime_arg2, tdots2, + errmsg ? errmsg : "success", + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)service_name.value, sdots, + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } + free(prime_arg1); + free(prime_arg2); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done(funcname, prime_arg, errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_get_principals", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_chpass_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_chpass_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_setv4key_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_setkey_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_setkey_principal", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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; + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done(funcname, prime_arg, errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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; + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done(funcname, prime_arg, errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_create_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_delete_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_modify_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done(funcname, + ((prime_arg == NULL) ? "(null)" : prime_arg), + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } else { + log_unauth(funcname, prime_arg, + &client_name, &service_name, rqstp); + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_get_policies", prime_arg, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + + 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))) + 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 = krb5_get_error_message(handle->context, ret.code); + + log_done("kadm5_get_privs", client_name.value, + errmsg ? errmsg : "success", + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); +exit_func: + free_server_handle(handle); + 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; + const char *errmsg = NULL; + 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(NULL, ret.code); + + clen = client_name.length; + trunc_name(&clen, &cdots); + slen = service_name.length; + trunc_name(&slen, &sdots); + /* okay to cast lengths to int because trunc_name limits max value */ + 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"), + (int)clen, (char *)client_name.value, cdots, + errmsg ? errmsg : "success", + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)service_name.value, sdots, + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), + rqstp->rq_cred.oa_flavor); + if (errmsg != NULL) + krb5_free_error_message(NULL, errmsg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); + +exit_func: + return(&ret); +} + +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-7/src/kadmin/testing/Makefile.in b/krb5-1-7/src/kadmin/testing/Makefile.in new file mode 100644 index 000000000..5b459950c --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/Makefile.in @@ -0,0 +1,10 @@ +thisconfigdir=../.. +myfulldir=kadmin/testing +mydir=kadmin/testing +BUILDTOP=$(REL)..$(S).. +SUBDIRS = scripts util + +all:: + +clean:: + -$(RM) -r krb5-test-root admin_* init-* kadmin_* kdc_rcache.* ovsec-* diff --git a/krb5-1-7/src/kadmin/testing/deps b/krb5-1-7/src/kadmin/testing/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/kadmin/testing/proto/kdc.conf.proto b/krb5-1-7/src/kadmin/testing/proto/kdc.conf.proto new file mode 100644 index 000000000..6f9edeb5b --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/proto/krb5.conf.proto b/krb5-1-7/src/kadmin/testing/proto/krb5.conf.proto new file mode 100644 index 000000000..b6ce16bff --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/proto/krb5.conf.proto @@ -0,0 +1,30 @@ +[libdefaults] + default_realm = __REALM__ + default_keytab_name = FILE:__K5ROOT__/v5srvtab + dns_fallback = no + allow_weak_crypto = true + +[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-7/src/kadmin/testing/proto/ovsec_adm.dict b/krb5-1-7/src/kadmin/testing/proto/ovsec_adm.dict new file mode 100644 index 000000000..b54e3a85e --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/proto/ovsec_adm.dict @@ -0,0 +1,3 @@ +Abyssinia +Discordianism +foo diff --git a/krb5-1-7/src/kadmin/testing/scripts/Makefile.in b/krb5-1-7/src/kadmin/testing/scripts/Makefile.in new file mode 100644 index 000000000..6161b1db8 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/compare_dump.plin b/krb5-1-7/src/kadmin/testing/scripts/compare_dump.plin new file mode 100755 index 000000000..df93df4a0 --- /dev/null +++ b/krb5-1-7/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() { + 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() { + 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() { + 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() { + 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-7/src/kadmin/testing/scripts/deps b/krb5-1-7/src/kadmin/testing/scripts/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/scripts/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/kadmin/testing/scripts/env-setup.shin b/krb5-1-7/src/kadmin/testing/scripts/env-setup.shin new file mode 100755 index 000000000..03e6d065e --- /dev/null +++ b/krb5-1-7/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 +# + +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-7/src/kadmin/testing/scripts/find-make.sh b/krb5-1-7/src/kadmin/testing/scripts/find-make.sh new file mode 100755 index 000000000..904730dfa --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/fixup-conf-files.plin b/krb5-1-7/src/kadmin/testing/scripts/fixup-conf-files.plin new file mode 100755 index 000000000..d7834d1c7 --- /dev/null +++ b/krb5-1-7/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 = ); + + $confok = 0; + + while() { + $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() { + $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() { +# 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() { +# 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() { +# if (/^([^:]+):\s*$/ && $mypass{$1}) { +# $user = $1; +# $users{$user}++; +# # arrange for the user to have a password entry and none other +# while () { +# 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 () { +# 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 <&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 10 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 < $K5ROOT/setup.csh < $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-7/src/kadmin/testing/scripts/qualname.plin b/krb5-1-7/src/kadmin/testing/scripts/qualname.plin new file mode 100755 index 000000000..883b7dfc8 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/save_files.sh b/krb5-1-7/src/kadmin/testing/scripts/save_files.sh new file mode 100755 index 000000000..72182036f --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/simple_dump.plin b/krb5-1-7/src/kadmin/testing/scripts/simple_dump.plin new file mode 100755 index 000000000..ea94ab2d1 --- /dev/null +++ b/krb5-1-7/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 = ; + +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() { + 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 = ; + +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() { + 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 = ; + $dummy = ; + $dummy = ; + + while() { + 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-7/src/kadmin/testing/scripts/start_servers b/krb5-1-7/src/kadmin/testing/scripts/start_servers new file mode 100755 index 000000000..b59d97b91 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/start_servers_local b/krb5-1-7/src/kadmin/testing/scripts/start_servers_local new file mode 100755 index 000000000..427e8ddd3 --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/scripts/start_servers_local @@ -0,0 +1,220 @@ +#!/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=1 +max_s=60 +sofar_s=0 +timewait_s=300 + +ovadm_args=-W + +while true; do + rm -f $adm_start_file + + (sleep 1; 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 <&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-7/src/kadmin/testing/scripts/stop_servers b/krb5-1-7/src/kadmin/testing/scripts/stop_servers new file mode 100755 index 000000000..9542fada8 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/stop_servers_local b/krb5-1-7/src/kadmin/testing/scripts/stop_servers_local new file mode 100755 index 000000000..15700f501 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/scripts/verify_xrunner_report.plin b/krb5-1-7/src/kadmin/testing/scripts/verify_xrunner_report.plin new file mode 100755 index 000000000..9d83c3ea2 --- /dev/null +++ b/krb5-1-7/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() { + 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() { + 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-7/src/kadmin/testing/tcl/util.t b/krb5-1-7/src/kadmin/testing/tcl/util.t new file mode 100644 index 000000000..0e39061f7 --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/util/Makefile.in b/krb5-1-7/src/kadmin/testing/util/Makefile.in new file mode 100644 index 000000000..ec09047cb --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/Makefile.in @@ -0,0 +1,44 @@ +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) diff --git a/krb5-1-7/src/kadmin/testing/util/bsddb_dump.c b/krb5-1-7/src/kadmin/testing/util/bsddb_dump.c new file mode 100644 index 000000000..ba69b8461 --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/bsddb_dump.c @@ -0,0 +1,64 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include + +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; iseq)(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-7/src/kadmin/testing/util/deps b/krb5-1-7/src/kadmin/testing/util/deps new file mode 100644 index 000000000..c822ad27b --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/deps @@ -0,0 +1,27 @@ +# +# Generated makefile dependencies follow. +# +$(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/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/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-7/src/kadmin/testing/util/tcl_kadm5.c b/krb5-1-7/src/kadmin/testing/util/tcl_kadm5.c new file mode 100644 index 000000000..df57a801f --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/tcl_kadm5.c @@ -0,0 +1,2545 @@ +#include "autoconf.h" +#include +#include +#if HAVE_TCL_H +#include +#elif HAVE_TCL_TCL_H +#include +#endif +#define USE_KADM5_API_VERSION 2 +#include +#include +#include +#include +#include +#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, const 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, const 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; \ + const 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, const char *in_str, char **out_str) +{ + if (! in_str) { + *out_str = 0; + } + else if (! strcasecmp(in_str, "null")) { + *out_str = 0; + } + else { + *out_str = (char *) 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 %ld (%s) ***\n", (long) 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, (char *) 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, const char *str, + krb5_flags *flags) +{ + int tmp, argc, i, retcode = TCL_OK; + const 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((char *) 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, const 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, const 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, const 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, const 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, const char *list, + krb5_key_salt_tuple **keysalts, + int num_keysalts) +{ + const 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((char *) argv1); + argv1 = NULL; + } + +finished: + if (argv1) { + Tcl_Free((char *) argv1); + } + Tcl_Free((char *) argv); + return retcode; +} + +static int parse_key_data(Tcl_Interp *interp, const char *list, + krb5_key_data **key_data, + int n_key_data) +{ + const 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((char *) argv); + return retcode; +} + +static int parse_tl_data(Tcl_Interp *interp, const char *list, + krb5_tl_data **tlp, + int n_tl_data) +{ + krb5_tl_data *tl, *tl2; + const 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 %lu of string \"%s\"", tmp, + (unsigned long) strlen(argv1[2]), argv1[2]); + retcode = TCL_ERROR; + goto finished; + } + tl->tl_data_contents = (krb5_octet *) strdup(argv1[2]); + + Tcl_Free((char *) 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((char *) argv1); + } + Tcl_Free((char *) argv); + return retcode; +} + +static int parse_config_params(Tcl_Interp *interp, char *list, + kadm5_config_params *params) +{ + static Tcl_HashTable *table = 0; + const 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; + } + /* Ignore argv[5], which used to set the admin_dbname field. */ + /* Ignore argv[6], which used to set the admin_lockfile field. */ + 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 = 0; + krb5_error_code krb5_ret; + int tcl_ret; + int argc; + const 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((char *) 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 = 0; + int tcl_ret; + int argc; + const 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((char *) 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, const char *argv[]) +{ + kadm5_ret_t ret; + char *client_name, *pass, *service_name; + int tcl_ret; + krb5_ui_4 struct_version, api_version; + const char *handle_var; + void *server_handle; + char *handle_name, *params_str; + const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const const 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, const 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, const 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, const 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, const 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, const 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, const 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, const char *argv[]) +{ + const 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-7/src/kadmin/testing/util/tcl_kadm5.h b/krb5-1-7/src/kadmin/testing/util/tcl_kadm5.h new file mode 100644 index 000000000..7e237753a --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/util/tcl_krb5_hash.c b/krb5-1-7/src/kadmin/testing/util/tcl_krb5_hash.c new file mode 100644 index 000000000..7fe1b8f74 --- /dev/null +++ b/krb5-1-7/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 +#elif HAVE_TCL_TCL_H +#include +#endif +#include + +#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-7/src/kadmin/testing/util/tcl_ovsec_kadm.c b/krb5-1-7/src/kadmin/testing/util/tcl_ovsec_kadm.c new file mode 100644 index 000000000..db0b4cc58 --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/tcl_ovsec_kadm.c @@ -0,0 +1,2036 @@ +#include "autoconf.h" +#include +#include +#if HAVE_TCL_H +#include +#elif HAVE_TCL_TCL_H +#include +#endif +#define USE_KADM5_API_VERSION 1 +#include +#include +#include +#include +#include "tcl_kadm5.h" +#include + +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, const 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, const 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; \ + const 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, const char *in_str, + char **out_str) +{ + if (! in_str) { + *out_str = 0; + } + else if (! strcasecmp(in_str, "null")) { + *out_str = 0; + } + else { + *out_str = (char *) 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 %ld (%s) ***\n", (long) 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, const char *str, + krb5_flags *flags) +{ + int tmp, argc, i, retcode = TCL_OK; + const 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((char *) 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, const 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, const 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, const 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, const 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, const char *list, + ovsec_kadm_principal_ent_t *out_princ) +{ + ovsec_kadm_principal_ent_t princ = 0; + krb5_error_code krb5_ret; + int tcl_ret; + int argc; + const 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((char *) 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 = 0; + int tcl_ret; + int argc; + const 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((char *) 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, const char *argv[]) +{ + ovsec_kadm_ret_t ret; + char *client_name, *pass, *service_name, *realm; + int tcl_ret; + krb5_ui_4 struct_version, api_version; + const char *handle_var; + void *server_handle; + char *handle_name; + const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const char *argv[]) +{ + const 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-7/src/kadmin/testing/util/tcl_ovsec_kadm_syntax b/krb5-1-7/src/kadmin/testing/util/tcl_ovsec_kadm_syntax new file mode 100644 index 000000000..3fc77fbcb --- /dev/null +++ b/krb5-1-7/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-7/src/kadmin/testing/util/test.c b/krb5-1-7/src/kadmin/testing/util/test.c new file mode 100644 index 000000000..ef8546deb --- /dev/null +++ b/krb5-1-7/src/kadmin/testing/util/test.c @@ -0,0 +1,38 @@ +#include "autoconf.h" +#if HAVE_TCL_H +#include +#elif HAVE_TCL_TCL_H +#include +#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-7/src/kdc/Makefile.in b/krb5-1-7/src/kdc/Makefile.in new file mode 100644 index 000000000..0d37fe1a1 --- /dev/null +++ b/krb5-1-7/src/kdc/Makefile.in @@ -0,0 +1,83 @@ +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) +DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\" + +all:: krb5kdc rtest + +# DEFINES = -DBACKWARD_COMPAT $(KRB4DEF) + +LOCALINCLUDES = -I. +SRCS= \ + kdc5_err.c \ + $(srcdir)/dispatch.c \ + $(srcdir)/do_as_req.c \ + $(srcdir)/do_tgs_req.c \ + $(srcdir)/fast_util.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)/kdc_authdata.c + +OBJS= \ + kdc5_err.o \ + dispatch.o \ + do_as_req.o \ + do_tgs_req.o \ + fast_util.o \ + kdc_util.o \ + kdc_preauth.o \ + main.o \ + network.o \ + policy.o \ + extern.o \ + replay.o \ + kdc_authdata.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) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB) + $(CC_LINK) -o krb5kdc $(OBJS) $(KADMSRV_LIBS) $(KRB5_BASE_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) + +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 + +clean:: + $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest + diff --git a/krb5-1-7/src/kdc/deps b/krb5-1-7/src/kdc/deps new file mode 100644 index 000000000..52ff5bc94 --- /dev/null +++ b/krb5-1-7/src/kdc/deps @@ -0,0 +1,145 @@ +# +# Generated makefile dependencies follow. +# +$(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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_ext.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_ext.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h do_tgs_req.c extern.h \ + kdc_util.h policy.h +$(OUTPRE)fast_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/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 fast_util.c kdc_util.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/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.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_ext.h \ + $(SRCTOP)/include/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_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.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 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/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 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/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 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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/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)kdc_authdata.$(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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_ext.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/authdata_plugin.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_authdata.c kdc_util.h diff --git a/krb5-1-7/src/kdc/dispatch.c b/krb5-1-7/src/kdc/dispatch.c new file mode 100644 index 000000000..36786457f --- /dev/null +++ b/krb5-1-7/src/kdc/dispatch.c @@ -0,0 +1,112 @@ +/* + * 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 +#include "kdc_util.h" +#include "extern.h" +#include "adm_proto.h" +#include +#include +#include + +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. + * process_as_req frees the request if it is called + */ + if (!(retval = setup_server_realm(as_req->server))) { + retval = process_as_req(as_req, pkt, from, response); + } + else krb5_free_kdc_req(kdc_context, as_req); + } + } + else + retval = KRB5KRB_AP_ERR_MSG_TYPE; +#ifndef NOCACHE + /* put the response into the lookaside buffer */ + if (!retval && *response != NULL) + kdc_insert_lookaside(pkt, *response); +#endif + + return retval; +} diff --git a/krb5-1-7/src/kdc/do_as_req.c b/krb5-1-7/src/kdc/do_as_req.c new file mode 100644 index 000000000..52fbda5d6 --- /dev/null +++ b/krb5-1-7/src/kdc/do_as_req.c @@ -0,0 +1,796 @@ +/* + * kdc/do_as_req.c + * + * Portions Copyright (C) 2007 Apple Inc. + * Copyright 1990,1991,2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + */ +/* + * Copyright (c) 2006-2008, 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" +#include "com_err.h" + +#include +#ifdef HAVE_NETINET_IN_H +#include +#include +#ifndef hpux +#include +#endif /* hpux */ +#endif /* HAVE_NETINET_IN_H */ + +#include "kdc_util.h" +#include "policy.h" +#include "adm.h" +#include "adm_proto.h" +#include "extern.h" + +#if APPLE_PKINIT +#define AS_REQ_DEBUG 0 +#if AS_REQ_DEBUG +#define asReqDebug(args...) printf(args) +#else +#define asReqDebug(args...) +#endif +#endif /* APPLE_PKINIT */ + +static krb5_error_code prepare_error_as (struct kdc_request_state *, krb5_kdc_req *, int, krb5_data *, + krb5_principal, 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 = 0; + krb5_keyblock session_key; + const char *status; + krb5_key_data *server_key, *client_key; + krb5_keyblock server_keyblock, client_keyblock; + krb5_keyblock *mkey_ptr; + krb5_enctype useenctype; + krb5_boolean update_client = 0; + krb5_data e_data; + register int i; + krb5_timestamp until, rtime; + char *cname = 0, *sname = 0; + unsigned int c_flags = 0, s_flags = 0; + krb5_principal_data client_princ; + void *pa_context = NULL; + int did_log = 0; + const char *emsg = 0; + krb5_keylist_node *tmp_mkey_list; + struct kdc_request_state *state = NULL; + krb5_data encoded_req_body; + krb5_keyblock *as_encrypting_key = NULL; + + +#if APPLE_PKINIT + asReqDebug("process_as_req top realm %s name %s\n", + request->client->realm.data, request->client->data->data); +#endif /* APPLE_PKINIT */ + + ticket_reply.enc_part.ciphertext.data = 0; + e_data.data = 0; + server_keyblock.contents = NULL; + client_keyblock.contents = NULL; + reply.padata = 0; + memset(&reply, 0, sizeof(reply)); + + session_key.contents = 0; + enc_tkt_reply.authorization_data = NULL; + + errcode = kdc_make_rstate(&state); + if (errcode != 0) { + status = "constructing state"; + goto errout; + } + if (fetch_asn1_field((unsigned char *) req_pkt->data, + 1, 4, &encoded_req_body) != 0) { + errcode = ASN1_BAD_ID; + status = "Finding req_body"; + goto errout; + } + errcode = kdc_find_fast(&request, &encoded_req_body, NULL /*TGS key*/, NULL, state); + if (errcode) { + status = "error decoding FAST"; + goto errout; + } + request->kdc_state = state; + 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); + + /* + * We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint + * to the backend to return naming information in lieu + * of cross realm TGS entries. + */ + setflag(c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY); + /* + * Note that according to the referrals draft we should + * always canonicalize enterprise principal names. + */ + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) || + krb5_princ_type(kdc_context, + request->client) == KRB5_NT_ENTERPRISE_PRINCIPAL) { + setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + } + if (include_pac_p(kdc_context, request)) { + setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); + } + c_nprincs = 1; + if ((errcode = krb5_db_get_principal_ext(kdc_context, request->client, + c_flags, &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; + } + + /* + * If the backend returned a principal that is not in the local + * realm, then we need to refer the client to that realm. + */ + if (!is_local_principal(client.princ)) { + /* Entry is a referral to another realm */ + status = "REFERRAL"; + errcode = KRB5KDC_ERR_WRONG_REALM; + goto errout; + } + +#if 0 + /* + * Turn off canonicalization if client is marked DES only + * (unless enterprise principal name was requested) + */ + if (isflagset(client.attributes, KRB5_KDB_NON_MS_PRINCIPAL) && + krb5_princ_type(kdc_context, + request->client) != KRB5_NT_ENTERPRISE_PRINCIPAL) { + clear(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + } +#endif + + s_flags = 0; + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE)) { + setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); + } + s_nprincs = 1; + if ((errcode = krb5_db_get_principal_ext(kdc_context, request->server, + s_flags, &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; + } + authtime = kdc_time; /* for audit_as_request() */ + + 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; + } + + /* + * Canonicalization is only effective if we are issuing a TGT + * (the intention is to allow support for Windows "short" realm + * aliases, nothing more). + */ + if (isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE) && + krb5_is_tgs_principal(request->server) && + krb5_is_tgs_principal(server.princ)) { + ticket_reply.server = server.princ; + } else { + ticket_reply.server = request->server; + } + + enc_tkt_reply.flags = 0; + enc_tkt_reply.times.authtime = authtime; + + 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; + if (isflagset(c_flags, KRB5_KDB_FLAG_CANONICALIZE)) { + client_princ = *(client.princ); + } else { + client_princ = *(request->client); + /* The realm is always canonicalized */ + client_princ.realm = *(krb5_princ_realm(context, client.princ)); + } + enc_tkt_reply.client = &client_princ; + enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; + enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */ + + 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) { + if (errcode == KRB5KDC_ERR_PREAUTH_FAILED) + get_preauth_hint_list(request, &client, &server, &e_data); + + if (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; + 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; + } + + if ((errcode = validate_forwardable(request, client, server, + kdc_time, &status))) { + errcode += ERROR_TABLE_BASE_krb5; + 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; + } + + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &server, + &mkey_ptr))) { + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(kdc_context, master_princ, + &master_keyblock, 0, &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(kdc_context, master_keylist); + master_keylist = tmp_mkey_list; + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, + &server, &mkey_ptr))) { + status = "FINDING_MASTER_KEY"; + goto errout; + } + } else { + status = "FINDING_MASTER_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, mkey_ptr, + /* server_keyblock is later used to generate auth data signatures */ + server_key, &server_keyblock, + NULL))) { + status = "DECRYPT_SERVER_KEY"; + goto errout; + } + + /* + * 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; + } + + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &client, + &mkey_ptr))) { + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(kdc_context, master_princ, + &master_keyblock, 0, &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(kdc_context, master_keylist); + master_keylist = tmp_mkey_list; + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, + &client, &mkey_ptr))) { + status = "FINDING_MASTER_KEY"; + goto errout; + } + } else { + status = "FINDING_MASTER_KEY"; + goto errout; + } + } + + /* convert client.key_data into a real key */ + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, + client_key, &client_keyblock, + NULL))) { + status = "DECRYPT_CLIENT_KEY"; + goto errout; + } + client_keyblock.enctype = useenctype; + + /* Start assembling the response */ + reply.msg_type = KRB5_AS_REP; + reply.client = enc_tkt_reply.client; /* post canonicalization */ + 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; + reply_encpart.enc_padata = NULL; + + /* Fetch the padata info to be returned (do this before + authdata to handle possible replacement of reply key */ + errcode = return_padata(kdc_context, &client, req_pkt, request, + &reply, client_key, &client_keyblock, &pa_context); + if (errcode) { + status = "KDC_RETURN_PADATA"; + goto errout; + } + +#if APPLE_PKINIT + asReqDebug("process_as_req reply realm %s name %s\n", + reply.client->realm.data, reply.client->data->data); +#endif /* APPLE_PKINIT */ + + errcode = return_svr_referral_data(kdc_context, + &server, &reply_encpart); + if (errcode) { + status = "KDC_RETURN_ENC_PADATA"; + goto errout; + } + + + errcode = handle_authdata(kdc_context, + c_flags, + &client, + &server, + &server, + &client_keyblock, + &server_keyblock, + req_pkt, + request, + NULL, /* for_user_princ */ + NULL, /* enc_tkt_request */ + &enc_tkt_reply); + if (errcode) { + krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode); + status = "HANDLE_AUTHDATA"; + goto errout; + } + + errcode = krb5_encrypt_tkt_part(kdc_context, &server_keyblock, &ticket_reply); + if (errcode) { + status = "ENCRYPTING_TICKET"; + goto errout; + } + ticket_reply.enc_part.kvno = server_key->key_data_kvno; + errcode = kdc_fast_response_handle_padata(state, request, &reply, client_keyblock.enctype); + if (errcode) { + status = "fast response handling"; + goto errout; + } + + /* now encode/encrypt the response */ + + reply.enc_part.enctype = client_keyblock.enctype; + + errcode = kdc_fast_handle_reply_key(state, &client_keyblock, &as_encrypting_key); + if (errcode) { + status = "generating reply key"; + goto errout; + } + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, + 0, as_encrypting_key, &reply, response); + 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); + + if (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; + + log_as_req(from, request, &reply, &client, cname, &server, sname, + authtime, 0, 0, 0); + did_log = 1; + + goto egress; + +errout: + assert (status != 0); + /* fall through */ + +egress: + if (pa_context) + free_padata_context(kdc_context, &pa_context); + if (as_encrypting_key) + krb5_free_keyblock(kdc_context, as_encrypting_key); + if (errcode) + emsg = krb5_get_error_message(kdc_context, errcode); + + if (status) { + log_as_req(from, request, &reply, &client, cname, &server, sname, 0, + status, errcode, emsg); + did_log = 1; + } + if (errcode) { + if (status == 0) { + status = emsg; + } + errcode -= ERROR_TABLE_BASE_krb5; + if (errcode < 0 || errcode > 128) + errcode = KRB_ERR_GENERIC; + + errcode = prepare_error_as(state, request, errcode, &e_data, + c_nprincs ? client.princ : NULL, + response, status); + status = 0; + } + if (emsg) + krb5_free_error_message(kdc_context, emsg); + + if (enc_tkt_reply.authorization_data != NULL) + krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data); + if (server_keyblock.contents != NULL) + krb5_free_keyblock_contents(kdc_context, &server_keyblock); + if (client_keyblock.contents != NULL) + krb5_free_keyblock_contents(kdc_context, &client_keyblock); + if (reply.padata != NULL) + krb5_free_pa_data(kdc_context, reply.padata); + + if (cname != NULL) + free(cname); + if (sname != NULL) + free(sname); + if (c_nprincs) { + if (kdc_modifies_kdb) { + if (update_client) { + krb5_error_code errcode2; + + krb5_db_put_principal(kdc_context, &client, &c_nprincs); + /* + * ptooey. We want krb5_db_sync() or something like that. + */ + errcode2 = krb5_db_fini(kdc_context); + if (errcode2 == 0) + errcode2 = krb5_db_open(kdc_context, db_args, + KRB5_KDB_OPEN_RW|KRB5_KDB_SRV_TYPE_KDC); + /* Reset master key */ + krb5_db_set_mkey(kdc_context, &kdc_active_realm->realm_mkey); + } + } + 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 != NULL) + krb5_free_keyblock_contents(kdc_context, &session_key); + if (ticket_reply.enc_part.ciphertext.data != NULL) { + 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); + kdc_free_rstate(state); + request->kdc_state = NULL; + krb5_free_kdc_req(kdc_context, request); + assert(did_log != 0); + return errcode; +} + +static krb5_error_code +prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, int error, krb5_data *e_data, + krb5_principal canon_client, krb5_data **response, + const char *status) +{ + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + krb5_pa_data **pa = NULL; + krb5_typed_data **td = NULL; + size_t size; + + 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 (error == KRB5KDC_ERR_WRONG_REALM) + errpkt.client = canon_client; + else + errpkt.client = request->client; + errpkt.text.length = strlen(status) + 1; + if (!(errpkt.text.data = strdup(status))) + return ENOMEM; + + if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { + free(errpkt.text.data); + return ENOMEM; + } + if (e_data != NULL&& e_data->data != NULL) { + errpkt.e_data = *e_data; + } else { + errpkt.e_data.length = 0; + errpkt.e_data.data = NULL; + } + /*We need to try and produce a padata sequence for FAST*/ + retval = decode_krb5_padata_sequence(e_data, &pa); + if (retval != 0) { + retval = decode_krb5_typed_data(e_data, &td); + if (retval == 0) { + for (size =0; td[size]; size++); + pa = calloc(size+1, sizeof(*pa)); + if (pa == NULL) + retval = ENOMEM; + else for (size = 0; td[size]; size++) { + krb5_pa_data *pad = malloc(sizeof(krb5_pa_data )); + if (pad == NULL) { + retval = ENOMEM; + break; + } + pad->pa_type = td[size]->type; + pad->contents = td[size]->data; + pad->length = td[size]->length; + pa[size] = pad; + } + krb5_free_typed_data(kdc_context, td); + } + } + retval = kdc_fast_handle_error(kdc_context, rstate, + request, pa, &errpkt); + if (retval == 0) + retval = krb5_mk_error(kdc_context, &errpkt, scratch); + free(errpkt.text.data); + if (retval) + free(scratch); + else + *response = scratch; + krb5_free_pa_data(kdc_context, pa); + return retval; +} diff --git a/krb5-1-7/src/kdc/do_tgs_req.c b/krb5-1-7/src/kdc/do_tgs_req.c new file mode 100644 index 000000000..12180ff93 --- /dev/null +++ b/krb5-1-7/src/kdc/do_tgs_req.c @@ -0,0 +1,1190 @@ +/* + * kdc/do_tgs_req.c + * + * Copyright 1990,1991,2001,2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + */ +/* + * Copyright (c) 2006-2008, 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" + +#include +#ifdef HAVE_NETINET_IN_H +#include +#include +#ifndef hpux +#include +#endif +#endif + +#include "kdc_util.h" +#include "policy.h" +#include "extern.h" +#include "adm_proto.h" +#include + +static void +find_alternate_tgs(krb5_kdc_req *,krb5_db_entry *, + krb5_boolean *,int *); + +static krb5_error_code +prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int, + krb5_principal,krb5_data **,const char *); + +static krb5_int32 +prep_reprocess_req(krb5_kdc_req *,krb5_principal *); + +/*ARGSUSED*/ +krb5_error_code +process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, + krb5_data **response) +{ + krb5_keyblock * subkey = 0; + 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; + krb5_keyblock encrypting_key; + int nprincs = 0; + krb5_boolean more; + krb5_timestamp kdc_time, authtime=0; + krb5_keyblock session_key; + krb5_timestamp until, rtime; + krb5_keyblock *reply_key = NULL; + krb5_keyblock *mkey_ptr; + krb5_key_data *server_key; + char *cname = 0, *sname = 0, *altcname = 0; + krb5_last_req_entry *nolrarray[2], nolrentry; + krb5_enctype useenctype; + int errcode, errcode2; + register int i; + int firstpass = 1; + const char *status = 0; + krb5_enc_tkt_part *header_enc_tkt = NULL; /* ticket granting or evidence ticket */ + krb5_db_entry client, krbtgt; + int c_nprincs = 0, k_nprincs = 0; + krb5_pa_for_user *for_user = NULL; /* protocol transition request */ + krb5_authdata **kdc_issued_auth_data = NULL; /* auth data issued by KDC */ + unsigned int c_flags = 0, s_flags = 0; /* client/server KDB flags */ + char *s4u_name = NULL; + krb5_boolean is_referral, db_ref_done = FALSE; + const char *emsg = NULL; + krb5_data *tgs_1 =NULL, *server_1 = NULL; + krb5_principal krbtgt_princ; + krb5_kvno ticket_kvno = 0; + struct kdc_request_state *state = NULL; + krb5_pa_data *pa_tgs_req; /*points into request*/ + krb5_data scratch; + + session_key.contents = NULL; + + retval = decode_krb5_tgs_req(pkt, &request); + if (retval) + return retval; + + /* + * setup_server_realm() sets up the global realm-specific data pointer. + */ + if ((retval = setup_server_realm(request->server))) { + krb5_free_kdc_req(kdc_context, request); + return retval; + } + errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket, + &krbtgt, &k_nprincs, &subkey, &pa_tgs_req); + 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; + } + errcode = kdc_make_rstate(&state); + if (errcode !=0) { + status = "making state"; + goto cleanup; + } + scratch.length = pa_tgs_req->length; + scratch.data = (char *) pa_tgs_req->contents; + errcode = kdc_find_fast(&request, &scratch, subkey, header_ticket->enc_part2->session, state); + if (errcode !=0) { + status = "kdc_find_fast"; + goto cleanup; + } + + + /* + * Pointer to the encrypted part of the header ticket, which may be + * replaced to point to the encrypted part of the evidence ticket + * if constrained delegation is used. This simplifies the number of + * special cases for constrained delegation. + */ + header_enc_tkt = header_ticket->enc_part2; + + /* + * 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. + */ + + /* XXX make sure server here has the proper realm...taken from AP_REQ + header? */ + + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE)) { + setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); + } + + db_ref_done = FALSE; +ref_tgt_again: + nprincs = 1; + if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { + status = "UNPARSING SERVER"; + goto cleanup; + } + limit_string(sname); + + errcode = krb5_db_get_principal_ext(kdc_context, + request->server, + s_flags, + &server, + &nprincs, + &more); + if (errcode) { + 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 ) { + + if ( krb5_is_tgs_principal(request->server) == TRUE) { /* Principal is a name of krb ticket service */ + if (krb5_princ_size(kdc_context, request->server) == 2) { + + server_1 = krb5_princ_component(kdc_context, request->server, 1); + tgs_1 = krb5_princ_component(kdc_context, tgs_server, 1); + + if (!tgs_1 || !data_eq(*server_1, *tgs_1)) { + 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; + + } else if ( db_ref_done == FALSE) { + retval = prep_reprocess_req(request, &krbtgt_princ); + if (!retval) { + krb5_free_principal(kdc_context, request->server); + retval = krb5_copy_principal(kdc_context, krbtgt_princ, &(request->server)); + if (!retval) { + db_ref_done = TRUE; + if (sname != NULL) + free(sname); + goto ref_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; + } + + if (!is_local_principal(header_enc_tkt->client)) + setflag(c_flags, KRB5_KDB_FLAG_CROSS_REALM); + + is_referral = krb5_is_tgs_principal(server.princ) && + !krb5_principal_compare(kdc_context, tgs_server, server.princ); + + /* Check for protocol transition */ + errcode = kdc_process_s4u2self_req(kdc_context, request, header_enc_tkt->client, + &server, header_enc_tkt->session, kdc_time, + &for_user, &client, &c_nprincs, &status); + if (errcode) + goto cleanup; + if (for_user != NULL) + setflag(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION); + + /* + * 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 | + KDC_OPT_CNAME_IN_ADDL_TKT)) { + krb5_keyblock * st_sealing_key; + krb5_kvno st_srv_kvno; + krb5_enctype etype; + krb5_db_entry st_client; + int st_nprincs = 0; + + /* + * Get the key for the second ticket, and decrypt it. + */ + if ((errcode = kdc_get_server_key(request->second_ticket[st_idx], + c_flags, + TRUE, /* match_enctype */ + &st_client, + &st_nprincs, + &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"; + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + 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; + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + goto cleanup; + } + + for (i = 0; i < request->nktypes; i++) { + if (request->ktype[i] == etype) { + useenctype = etype; + break; + } + } + + if (isflagset(request->kdc_options, KDC_OPT_CNAME_IN_ADDL_TKT)) { + /* Do constrained delegation protocol and authorization checks */ + errcode = kdc_process_s4u2proxy_req(kdc_context, + request, + request->second_ticket[st_idx]->enc_part2, + &st_client, + header_ticket->enc_part2->client, + request->server, + &status); + if (errcode) + goto cleanup; + + setflag(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); + + assert(krb5_is_tgs_principal(header_ticket->server)); + + /* From now on, use evidence ticket as header ticket */ + header_enc_tkt = request->second_ticket[st_idx]->enc_part2; + + assert(c_nprincs == 0); /* assured by kdc_process_s4u2self_req() */ + + client = st_client; + c_nprincs = st_nprincs; + } else { + /* "client" is not used for user2user */ + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + } + } + + /* + * 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; + } + + authtime = header_enc_tkt->times.authtime; + + if (is_referral) + ticket_reply.server = server.princ; + else + ticket_reply.server = request->server; /* XXX careful for realm... */ + + enc_tkt_reply.flags = 0; + enc_tkt_reply.times.starttime = 0; + + if (isflagset(server.attributes, KRB5_KDB_OK_AS_DELEGATE)) + setflag(enc_tkt_reply.flags, TKT_FLG_OK_AS_DELEGATE); + + /* + * Fix header_ticket's starttime; if it's zero, fill in the + * authtime's value. + */ + if (!(header_enc_tkt->times.starttime)) + header_enc_tkt->times.starttime = header_enc_tkt->times.authtime; + + /* don't use new addresses unless forwarded, see below */ + + enc_tkt_reply.caddrs = header_enc_tkt->caddrs; + /* noaddrarray[0] = 0; */ + reply_encpart.caddrs = 0;/* optional...don't put it in */ + reply_encpart.enc_padata = NULL; + + /* 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(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) { + if (!krb5_is_tgs_principal(server.princ) && + is_local_principal(server.princ)) { + if (isflagset(server.attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) + setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + else + clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + } + if (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) + clear(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_enc_tkt->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)) { + assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); + /* 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; + + assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); + /* 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_enc_tkt->times.endtime))); + if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && + (enc_tkt_reply.times.endtime < request->till) && + isflagset(header_enc_tkt->flags, TKT_FLG_RENEWABLE)) { + setflag(request->kdc_options, KDC_OPT_RENEWABLE); + request->rtime = + min(request->till, header_enc_tkt->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_enc_tkt->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_enc_tkt->times.authtime; + + /* + * Propagate the preauthentication flags through to the returned ticket. + */ + if (isflagset(header_enc_tkt->flags, TKT_FLG_PRE_AUTH)) + setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH); + + if (isflagset(header_enc_tkt->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; + + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) { + errcode = krb5_unparse_name(kdc_context, for_user->user, &s4u_name); + } else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { + errcode = krb5_unparse_name(kdc_context, header_enc_tkt->client, &s4u_name); + } else { + errcode = 0; + } + if (errcode) { + status = "UNPARSING S4U CLIENT"; + goto cleanup; + } + + if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) { + krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2; + encrypting_key = *(t2enc->session); + } 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; + } + + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &server, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(kdc_context, master_princ, + &master_keyblock, 0, &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(kdc_context, master_keylist); + master_keylist = tmp_mkey_list; + if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, + &server, &mkey_ptr))) { + status = "FINDING_MASTER_KEY"; + goto cleanup; + } + } else { + status = "FINDING_MASTER_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, + mkey_ptr, + server_key, &encrypting_key, + NULL))) { + status = "DECRYPT_SERVER_KEY"; + goto cleanup; + } + } + + if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { + /* + * Don't allow authorization data to be disabled if constrained + * delegation is requested. We don't want to deny the server + * the ability to validate that delegation was used. + */ + clear(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED); + } + if (isflagset(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED) == 0) { + /* + * If we are not doing protocol transition/constrained delegation + * and there was no authorization data included, try to lookup + * the client principal as it may be mapped to a local account. + * + * Always validate authorization data for constrained delegation + * because we must validate the KDC signatures. + */ + if (!isflagset(c_flags, KRB5_KDB_FLAGS_S4U) && + header_enc_tkt->authorization_data == NULL) { + + /* Generate authorization data so we can include it in ticket */ + setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); + /* Map principals from foreign (possibly non-AD) realms */ + setflag(c_flags, KRB5_KDB_FLAG_MAP_PRINCIPALS); + + assert(c_nprincs == 0); /* should not have been looked up already */ + + c_nprincs = 1; + errcode = krb5_db_get_principal_ext(kdc_context, + header_enc_tkt->client, + c_flags, + &client, + &c_nprincs, + &more); + /* + * We can ignore errors because the principal may be a + * valid cross-realm principal for which we have no local + * mapping. But we do want to check that at most one entry + * was returned. + */ + if (errcode == 0 && (more || c_nprincs > 1)) { + errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + goto cleanup; + } else if (errcode) { + c_nprincs = 0; + } + } + } + + enc_tkt_reply.authorization_data = NULL; + + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) && + is_local_principal(header_enc_tkt->client)) + enc_tkt_reply.client = for_user->user; + else + enc_tkt_reply.client = header_enc_tkt->client; + + errcode = handle_authdata(kdc_context, + c_flags, + (c_nprincs != 0) ? &client : NULL, + &server, + (k_nprincs != 0) ? &krbtgt : NULL, + subkey != NULL ? subkey : + header_ticket->enc_part2->session, + &encrypting_key, /* U2U or server key */ + pkt, + request, + for_user ? for_user->user : NULL, + header_enc_tkt, + &enc_tkt_reply); + if (errcode) { + krb5_klog_syslog(LOG_INFO, "TGS_REQ : handle_authdata (%d)", errcode); + status = "HANDLE_AUTHDATA"; + goto cleanup; + } + + if (is_referral && isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE)) { + errcode = return_svr_referral_data(kdc_context, + &server, &reply_encpart); + if (errcode) { + status = "KDC_RETURN_ENC_PADATA"; + goto cleanup; + } + } + + enc_tkt_reply.session = &session_key; + 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_enc_tkt->transited; + } else { + /* tgt issued by some other realm and not the realm of the client */ + /* assemble new transited field into allocated storage */ + if (header_enc_tkt->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_enc_tkt->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(c_flags, KRB5_KDB_FLAG_CROSS_REALM)) { + errcode = validate_transit_path(kdc_context, header_enc_tkt->client, + &server, + (k_nprincs != 0) ? &krbtgt : NULL); + if (errcode) { + status = "NON_TRANSITIVE"; + goto cleanup; + } + } + if (!isflagset (request->kdc_options, KDC_OPT_DISABLE_TRANSITED_CHECK)) { + unsigned int tlen; + char *tdots; + + errcode = kdc_check_transited_list (kdc_context, + &enc_tkt_reply.transited.tr_contents, + krb5_princ_realm (kdc_context, header_enc_tkt->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 : "", + sname ? sname : "", + tlen, + enc_tkt_reply.transited.tr_contents.data, + tdots); + else { + 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 : "", + sname ? sname : "", + tlen, + enc_tkt_reply.transited.tr_contents.data, + tdots, emsg); + krb5_free_error_message(kdc_context, emsg); + emsg = NULL; + } + } 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, &altcname))) + altcname = 0; + if (altcname != NULL) + limit_string(altcname); + + errcode = KRB5KDC_ERR_SERVER_NOMATCH; + status = "2ND_TKT_MISMATCH"; + goto cleanup; + } + + ticket_kvno = 0; + ticket_reply.enc_part.enctype = t2enc->session->enctype; + st_idx++; + } else { + ticket_kvno = server_key->key_data_kvno; + } + + errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, + &ticket_reply); + if (!isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) + krb5_free_keyblock_contents(kdc_context, &encrypting_key); + if (errcode) { + status = "TKT_ENCRYPT"; + goto cleanup; + } + ticket_reply.enc_part.kvno = ticket_kvno; + /* Start assembling the response */ + reply.msg_type = KRB5_TGS_REP; + reply.padata = 0;/* always */ + reply.client = enc_tkt_reply.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_enc_tkt->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 = kdc_fast_response_handle_padata(state, request, &reply, + subkey?subkey->enctype:header_ticket->enc_part2->session->enctype); + if (errcode !=0 ) { + status = "Preparing FAST padata"; + goto cleanup; + } + errcode =kdc_fast_handle_reply_key(state, subkey?subkey:header_ticket->enc_part2->session, &reply_key); + if (errcode) { + status = "generating reply key"; + goto cleanup; + } + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, + subkey ? 1 : 0, + reply_key, + &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: + assert(status != NULL); + if (reply_key) + krb5_free_keyblock(kdc_context, reply_key); + if (errcode) + emsg = krb5_get_error_message (kdc_context, errcode); + log_tgs_req(from, request, &reply, cname, sname, altcname, authtime, + c_flags, s4u_name, status, errcode, emsg); + if (errcode) { + krb5_free_error_message (kdc_context, emsg); + emsg = NULL; + } + + 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(state, request, header_ticket, errcode, + nprincs ? server.princ : NULL, + response, status); + if (got_err) { + krb5_free_error_message (kdc_context, status); + status = 0; + } + } + + if (header_ticket != NULL) + krb5_free_ticket(kdc_context, header_ticket); + if (request != NULL) + krb5_free_kdc_req(kdc_context, request); + if (state) + kdc_free_rstate(state); + if (cname != NULL) + free(cname); + if (sname != NULL) + free(sname); + if (nprincs != 0) + krb5_db_free_principal(kdc_context, &server, 1); + if (session_key.contents != NULL) + krb5_free_keyblock_contents(kdc_context, &session_key); + if (newtransited) + free(enc_tkt_reply.transited.tr_contents.data); + if (k_nprincs) + krb5_db_free_principal(kdc_context, &krbtgt, k_nprincs); + if (c_nprincs) + krb5_db_free_principal(kdc_context, &client, c_nprincs); + if (for_user != NULL) + krb5_free_pa_for_user(kdc_context, for_user); + if (kdc_issued_auth_data != NULL) + krb5_free_authdata(kdc_context, kdc_issued_auth_data); + if (s4u_name != NULL) + free(s4u_name); + if (subkey != NULL) + krb5_free_keyblock(kdc_context, subkey); + + return retval; +} + +static krb5_error_code +prepare_error_tgs (struct kdc_request_state *state, + krb5_kdc_req *request, krb5_ticket *ticket, int error, + krb5_principal canon_server, + krb5_data **response, const char *status) +{ + krb5_error errpkt; + krb5_error_code retval = 0; + 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 = NULL; + errpkt.text.length = strlen(status) + 1; + if (!(errpkt.text.data = strdup(status))) + return ENOMEM; + + if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { + free(errpkt.text.data); + return ENOMEM; + } + errpkt.e_data.length = 0; + errpkt.e_data.data = NULL; + if (state) + retval = kdc_fast_handle_error(kdc_context, state, request, NULL, &errpkt); + if (retval) { + free(scratch); + free(errpkt.text.data); + return retval; + } + 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 = 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; + + 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; + log_tgs_alt_tgt(request->server); + krb5_free_realm_tree(kdc_context, plist); + return; + } + krb5_db_free_principal(kdc_context, server, *nprincs); + continue; + } + + *nprincs = 0; + *more = FALSE; + krb5_free_realm_tree(kdc_context, plist); + return; +} + +static krb5_int32 +prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) +{ + krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH; + size_t len = 0; + char **realms, **cpp, *temp_buf=NULL; + krb5_data *comp1 = NULL, *comp2 = NULL; + char *comp1_str = NULL; + + /* By now we know that server principal name is unknown. + * If CANONICALIZE flag is set in the request + * If req is not U2U authn. req + * the requested server princ. has exactly two components + * either + * the name type is NT-SRV-HST + * or name type is NT-UNKNOWN and + * the 1st component is listed in conf file under host_based_services + * the 1st component is not in a list in conf under "no_host_referral" + * the 2d component looks like fully-qualified domain name (FQDN) + * If all of these conditions are satisfied - try mapping the FQDN and + * re-process the request as if client had asked for cross-realm TGT. + */ + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) && + !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && + krb5_princ_size(kdc_context, request->server) == 2) { + + comp1 = krb5_princ_component(kdc_context, request->server, 0); + comp2 = krb5_princ_component(kdc_context, request->server, 1); + + comp1_str = calloc(1,comp1->length+1); + if (!comp1_str) { + retval = ENOMEM; + goto cleanup; + } + strlcpy(comp1_str,comp1->data,comp1->length+1); + + if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || + (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && + kdc_active_realm->realm_host_based_services != NULL && + (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE || + krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) && + (kdc_active_realm->realm_no_host_referral == NULL || + (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE && + krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) { + + for (len=0; len < comp2->length; len++) { + if (comp2->data[len] == '.') break; + } + if (len == comp2->length) + goto cleanup; + temp_buf = calloc(1, comp2->length+1); + if (!temp_buf){ + retval = ENOMEM; + goto cleanup; + } + strlcpy(temp_buf, comp2->data,comp2->length+1); + retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms); + free(temp_buf); + if (retval) { + /* no match found */ + kdc_err(kdc_context, retval, "unable to find realm of host"); + goto cleanup; + } + if (realms == 0) { + retval = KRB5KRB_AP_ERR_BADMATCH; + goto cleanup; + } + if (realms[0] == 0) { + free(realms); + retval = KRB5KRB_AP_ERR_BADMATCH; + goto cleanup; + } + /* Modify request. + * Construct cross-realm tgt : krbtgt/REMOTE_REALM@LOCAL_REALM + * and use it as a principal in this req. + */ + retval = krb5_build_principal(kdc_context, krbtgt_princ, + (*request->server).realm.length, + (*request->server).realm.data, + "krbtgt", realms[0], (char *)0); + for (cpp = realms; *cpp; cpp++) + free(*cpp); + } + } +cleanup: + free(comp1_str); + return retval; +} + + diff --git a/krb5-1-7/src/kdc/extern.c b/krb5-1-7/src/kdc/extern.c new file mode 100644 index 000000000..3427bcfff --- /dev/null +++ b/krb5-1-7/src/kdc/extern.c @@ -0,0 +1,49 @@ +/* + * 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 "kdb.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; +#ifdef KRBCONF_KDC_MODIFIES_KDB +const int kdc_modifies_kdb = 1; +#else +const int kdc_modifies_kdb = 0; +#endif +krb5_int32 max_dgram_reply_size = MAX_DGRAM_SIZE; + +volatile int signal_requests_exit = 0; /* gets set when signal hits */ +volatile int signal_requests_hup = 0; /* ditto */ diff --git a/krb5-1-7/src/kdc/extern.h b/krb5-1-7/src/kdc/extern.h new file mode 100644 index 000000000..87cc1bfa0 --- /dev/null +++ b/krb5-1-7/src/kdc/extern.h @@ -0,0 +1,110 @@ +/* + * kdc/extern.h + * + * Copyright 1990,2001,2007,2009 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 */ + char * realm_host_based_services; /* do referral processing for these services + * If '*' - allow all referrals */ + char * realm_no_host_referral; /* no referral for these services. + * If '*' - disallow all referrals and + * ignore realm_host_based_services */ + /* + * 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 */ + /* + * Note realm_mkey is mkey read from stash or keyboard and may not be the + * latest. The mkey_list will have all the mkeys in use. + */ + krb5_keyblock realm_mkey; /* Master key for this realm */ + krb5_keylist_node * mkey_list; /* list of mkeys in use 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_keylist kdc_active_realm->mkey_list +#define master_princ kdc_active_realm->realm_mprinc +#define tgs_server kdc_active_realm->realm_tgsprinc +#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 const int kdc_modifies_kdb; +extern char **db_args; +extern krb5_int32 max_dgram_reply_size; /* maximum datagram size */ + +extern volatile int signal_requests_exit; +extern volatile int signal_requests_hup; +#endif /* __KRB5_KDC_EXTERN__ */ diff --git a/krb5-1-7/src/kdc/fast_util.c b/krb5-1-7/src/kdc/fast_util.c new file mode 100644 index 000000000..d88e0cb21 --- /dev/null +++ b/krb5-1-7/src/kdc/fast_util.c @@ -0,0 +1,489 @@ +/* + * kdc/fast_util.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kdc_util.h" +#include "extern.h" + + +/* + * This function will find the fast and cookie padata and if fast is + * successfully processed, will throw away (and free) the outer + * request and update the pointer to point to the inner request. The + * checksummed_data points to the data that is in the + * armored_fast_request checksum; either the pa-tgs-req or the + * kdc-req-body. + */ + +static krb5_error_code armor_ap_request +(struct kdc_request_state *state, krb5_fast_armor *armor) +{ + krb5_error_code retval = 0; + krb5_auth_context authcontext = NULL; + krb5_ticket *ticket = NULL; + krb5_keyblock *subkey = NULL; + + assert(armor->armor_type == KRB5_FAST_ARMOR_AP_REQUEST); + krb5_clear_error_message(kdc_context); + retval = krb5_auth_con_init(kdc_context, &authcontext); + if (retval == 0) + retval = krb5_auth_con_setflags(kdc_context, authcontext, 0); /*disable replay cache*/ + retval = krb5_rd_req(kdc_context, &authcontext, + &armor->armor_value, NULL /*server*/, + kdc_active_realm->realm_keytab, NULL, &ticket); + if (retval !=0) { + const char * errmsg = krb5_get_error_message(kdc_context, retval); + krb5_set_error_message(kdc_context, retval, + "%s while handling ap-request armor", errmsg); + krb5_free_error_message(kdc_context, errmsg); + } + if (retval == 0) { + if (!krb5_principal_compare_any_realm(kdc_context, + tgs_server, + ticket->server)) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_SERVER_NOMATCH, + "ap-request armor for something other than the local TGS"); + retval = KRB5KDC_ERR_SERVER_NOMATCH; + } + } + if (retval ==0) { + retval = krb5_auth_con_getrecvsubkey(kdc_context, authcontext, &subkey); + if (retval !=0 || subkey == NULL) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "ap-request armor without subkey"); + retval = KRB5KDC_ERR_POLICY; + } + } + if (retval==0) + retval = krb5_c_fx_cf2_simple(kdc_context, + subkey, "subkeyarmor", + ticket->enc_part2->session, "ticketarmor", + &state->armor_key); + if (ticket) + krb5_free_ticket(kdc_context, ticket); + if (subkey) + krb5_free_keyblock(kdc_context, subkey); + if (authcontext) + krb5_auth_con_free(kdc_context, authcontext); + return retval; +} + +static krb5_error_code encrypt_fast_reply +(struct kdc_request_state *state, const krb5_fast_response *response, + krb5_data **fx_fast_reply) +{ + krb5_error_code retval = 0; + krb5_enc_data encrypted_reply; + krb5_data *encoded_response = NULL; + assert(state->armor_key); + retval = encode_krb5_fast_response(response, &encoded_response); + if (retval== 0) + retval = krb5_encrypt_helper(kdc_context, state->armor_key, + KRB5_KEYUSAGE_FAST_REP, + encoded_response, &encrypted_reply); + if (encoded_response) + krb5_free_data(kdc_context, encoded_response); + encoded_response = NULL; + if (retval == 0) { + retval = encode_krb5_pa_fx_fast_reply(&encrypted_reply, + fx_fast_reply); + krb5_free_data_contents(kdc_context, &encrypted_reply.ciphertext); + } + return retval; +} + + +krb5_error_code kdc_find_fast +(krb5_kdc_req **requestptr, krb5_data *checksummed_data, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + struct kdc_request_state *state) +{ + krb5_error_code retval = 0; + krb5_pa_data *fast_padata, *cookie_padata; + krb5_data scratch; + krb5_fast_req * fast_req = NULL; + krb5_kdc_req *request = *requestptr; + krb5_fast_armored_req *fast_armored_req = NULL; + krb5_boolean cksum_valid; + krb5_keyblock empty_keyblock; + + scratch.data = NULL; + krb5_clear_error_message(kdc_context); + memset(&empty_keyblock, 0, sizeof(krb5_keyblock)); + fast_padata = find_pa_data(request->padata, + KRB5_PADATA_FX_FAST); + if (fast_padata != NULL){ + scratch.length = fast_padata->length; + scratch.data = (char *) fast_padata->contents; + retval = decode_krb5_pa_fx_fast_request(&scratch, &fast_armored_req); + if (retval == 0 &&fast_armored_req->armor) { + switch (fast_armored_req->armor->armor_type) { + case KRB5_FAST_ARMOR_AP_REQUEST: + if (tgs_subkey) { + krb5_set_error_message( kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, + "Ap-request armor not permitted with TGS"); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + break; + } + retval = armor_ap_request(state, fast_armored_req->armor); + break; + default: + krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, + "Unknow FAST armor type %d", + fast_armored_req->armor->armor_type); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0 && !state->armor_key) { + if (tgs_subkey) + retval = krb5_c_fx_cf2_simple(kdc_context, + tgs_subkey, "subkeyarmor", + tgs_session, "ticketarmor", + &state->armor_key); + else { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, + "No armor key but FAST armored request present"); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0) { + krb5_data plaintext; + plaintext.length = fast_armored_req->enc_part.ciphertext.length; + plaintext.data = malloc(plaintext.length); + if (plaintext.data == NULL) + retval = ENOMEM; + retval = krb5_c_decrypt(kdc_context, + state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, NULL, + &fast_armored_req->enc_part, + &plaintext); + if (retval == 0) + retval = decode_krb5_fast_req(&plaintext, &fast_req); + if (plaintext.data) + free(plaintext.data); + } + if (retval == 0) + retval = krb5_c_verify_checksum(kdc_context, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + checksummed_data, &fast_armored_req->req_checksum, + &cksum_valid); + if (retval == 0 && !cksum_valid) { + retval = KRB5KRB_AP_ERR_MODIFIED; + krb5_set_error_message(kdc_context, KRB5KRB_AP_ERR_MODIFIED, + "FAST req_checksum invalid; request modified"); + } + if (retval == 0) { + krb5_error_code ret; + /* We need to confirm that a keyed checksum is used for the + * fast_req checksum. In April 2009, the best way to do this is + * to try verifying the checksum with a keyblock with an zero + * length; if it succeeds, then an unkeyed checksum is used.*/ + ret = krb5_c_verify_checksum(kdc_context, &empty_keyblock, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + checksummed_data, &fast_armored_req->req_checksum, + &cksum_valid); + if (ret == 0) { + retval = KRB5KDC_ERR_POLICY; + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "Unkeyed checksum used in fast_req"); + } + } + if (retval == 0) { + if ((fast_req->fast_options & UNSUPPORTED_CRITICAL_FAST_OPTIONS) !=0) + retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION; + } + if (retval == 0) + cookie_padata = find_pa_data(fast_req->req_body->padata, KRB5_PADATA_FX_COOKIE); + if (retval == 0) { + state->fast_options = fast_req->fast_options; + if (request->kdc_state == state) + request->kdc_state = NULL; + krb5_free_kdc_req( kdc_context, request); + *requestptr = fast_req->req_body; + fast_req->req_body = NULL; + + } + } + else cookie_padata = find_pa_data(request->padata, KRB5_PADATA_FX_COOKIE); + if (retval == 0 && cookie_padata != NULL) { + krb5_pa_data *new_padata = malloc(sizeof (krb5_pa_data)); + if (new_padata == NULL) { + retval = ENOMEM; + } else { + new_padata->pa_type = KRB5_PADATA_FX_COOKIE; + new_padata->length = cookie_padata->length; + new_padata->contents = malloc(new_padata->length); + if (new_padata->contents == NULL) { + retval = ENOMEM; + free(new_padata); + } else { + memcpy(new_padata->contents, cookie_padata->contents, new_padata->length); + state->cookie = new_padata; + } + } + } + if (fast_req) + krb5_free_fast_req( kdc_context, fast_req); + if (fast_armored_req) + krb5_free_fast_armored_req(kdc_context, fast_armored_req); + return retval; +} + + +krb5_error_code kdc_make_rstate(struct kdc_request_state **out) +{ + struct kdc_request_state *state = malloc( sizeof(struct kdc_request_state)); + if (state == NULL) + return ENOMEM; + memset( state, 0, sizeof(struct kdc_request_state)); + *out = state; + return 0; +} + +void kdc_free_rstate +(struct kdc_request_state *s) +{ + if (s == NULL) + return; + if (s->armor_key) + krb5_free_keyblock(kdc_context, s->armor_key); + if (s->strengthen_key) + krb5_free_keyblock(kdc_context, s->strengthen_key); + if (s->cookie) { + free(s->cookie->contents); + free(s->cookie); + } + free(s); +} + +krb5_error_code kdc_fast_response_handle_padata +(struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_kdc_rep *rep, krb5_enctype enctype) +{ + krb5_error_code retval = 0; + krb5_fast_finished finish; + krb5_fast_response fast_response; + krb5_data *encoded_ticket = NULL; + krb5_data *encrypted_reply = NULL; + krb5_pa_data *pa = NULL, **pa_array = NULL; + krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5; + krb5_pa_data *empty_padata[] = {NULL}; + krb5_keyblock *strengthen_key = NULL; + + if (!state->armor_key) + return 0; + memset(&finish, 0, sizeof(finish)); + retval = krb5_init_keyblock(kdc_context, enctype, 0, &strengthen_key); + if (retval == 0) + retval = krb5_c_make_random_key(kdc_context, enctype, strengthen_key); + if (retval == 0) { + state->strengthen_key = strengthen_key; + strengthen_key = NULL; + } + + fast_response.padata = rep->padata; + if (fast_response.padata == NULL) + fast_response.padata = &empty_padata[0]; + fast_response.strengthen_key = state->strengthen_key; + fast_response.nonce = request->nonce; + fast_response.finished = &finish; + finish.client = rep->client; + pa_array = calloc(3, sizeof(*pa_array)); + if (pa_array == NULL) + retval = ENOMEM; + pa = calloc(1, sizeof(krb5_pa_data)); + if (retval == 0 && pa == NULL) + retval = ENOMEM; + if (retval == 0) + retval = krb5_us_timeofday(kdc_context, &finish.timestamp, &finish.usec); + if (retval == 0) + retval = encode_krb5_ticket(rep->ticket, &encoded_ticket); + if (retval == 0) + retval = krb5int_c_mandatory_cksumtype(kdc_context, state->armor_key->enctype, &cksumtype); + if (retval == 0) + retval = krb5_c_make_checksum(kdc_context, cksumtype, + state->armor_key, KRB5_KEYUSAGE_FAST_FINISHED, + encoded_ticket, &finish.ticket_checksum); + if (retval == 0) + retval = encrypt_fast_reply(state, &fast_response, &encrypted_reply); + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + pa_array[0] = &pa[0]; + rep->padata = pa_array; + pa_array = NULL; + free(encrypted_reply); + encrypted_reply = NULL; + pa = NULL; + } + if (pa) + free(pa); + if (pa_array) + free(pa_array); + if (encrypted_reply) + krb5_free_data(kdc_context, encrypted_reply); + if (encoded_ticket) + krb5_free_data(kdc_context, encoded_ticket); + if (strengthen_key != NULL) + krb5_free_keyblock(kdc_context, strengthen_key); + if (finish.ticket_checksum.contents) + krb5_free_checksum_contents(kdc_context, &finish.ticket_checksum); + return retval; +} + + +/* + * We assume the caller is responsible for passing us an in_padata + * sufficient to include in a FAST error. In the FAST case we will + * throw away the e_data in the error (if any); in the non-FAST case + * we will not use the in_padata. + */ +krb5_error_code kdc_fast_handle_error +(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_pa_data **in_padata, krb5_error *err) +{ + krb5_error_code retval = 0; + krb5_fast_response resp; + krb5_error fx_error; + krb5_data *encoded_fx_error = NULL, *encrypted_reply = NULL; + krb5_pa_data pa[1]; + krb5_pa_data *outer_pa[3], *cookie = NULL; + krb5_pa_data **inner_pa = NULL; + size_t size = 0; + krb5_data *encoded_e_data = NULL; + + memset(outer_pa, 0, sizeof(outer_pa)); + if (!state->armor_key) + return 0; + fx_error = *err; + fx_error.e_data.data = NULL; + fx_error.e_data.length = 0; + for (size = 0; in_padata&&in_padata[size]; size++); + size +=3; + inner_pa = calloc(size, sizeof(krb5_pa_data *)); + if (inner_pa == NULL) + retval = ENOMEM; + if (retval == 0) + for (size=0; in_padata&&in_padata[size]; size++) + inner_pa[size] = in_padata[size]; + if (retval == 0) + retval = encode_krb5_error(&fx_error, &encoded_fx_error); + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_ERROR; + pa[0].length = encoded_fx_error->length; + pa[0].contents = (unsigned char *) encoded_fx_error->data; + inner_pa[size++] = &pa[0]; + if (find_pa_data(inner_pa, KRB5_PADATA_FX_COOKIE) == NULL) + retval = kdc_preauth_get_cookie(state, &cookie); + } + if (cookie != NULL) + inner_pa[size++] = cookie; + if (retval == 0) { + resp.padata = inner_pa; + resp.nonce = request->nonce; + resp.strengthen_key = NULL; + resp.finished = NULL; + } + if (retval == 0) + retval = encrypt_fast_reply(state, &resp, &encrypted_reply); + if (inner_pa) + free(inner_pa); /*contained storage from caller and our stack*/ + if (cookie) { + free(cookie->contents); + free(cookie); + cookie = NULL; + } + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + outer_pa[0] = &pa[0]; + } + retval = encode_krb5_padata_sequence(outer_pa, &encoded_e_data); + if (retval == 0) { + /*process_as holds onto a pointer to the original e_data and frees it*/ + err->e_data = *encoded_e_data; + free(encoded_e_data); /*contents belong to err*/ + encoded_e_data = NULL; + } + if (encoded_e_data) + krb5_free_data(kdc_context, encoded_e_data); + if (encrypted_reply) + krb5_free_data(kdc_context, encrypted_reply); + if (encoded_fx_error) + krb5_free_data(kdc_context, encoded_fx_error); + return retval; +} + +krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key) +{ + krb5_error_code retval = 0; + if (state->armor_key) + retval = krb5_c_fx_cf2_simple(kdc_context, + state->strengthen_key, "strengthenkey", + existing_key, + "replykey", out_key); + else retval = krb5_copy_keyblock(kdc_context, existing_key, out_key); + return retval; +} + + +krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, + krb5_pa_data **cookie) +{ + char *contents; + krb5_pa_data *pa = NULL; + /* In our current implementation, the only purpose served by + * returning a cookie is to indicate that a conversation should + * continue on error. Thus, the cookie can have a constant + * string. If cookies are used for real, versioning so that KDCs + * can be upgraded, keying, expiration and many other issues need + * to be considered. + */ + contents = strdup("MIT"); + if (contents == NULL) + return ENOMEM; + pa = calloc(1, sizeof(krb5_pa_data)); + if (pa == NULL) { + free(contents); + return ENOMEM; + } + pa->pa_type = KRB5_PADATA_FX_COOKIE; + pa->length = strlen(contents); + pa->contents = (unsigned char *) contents; + *cookie = pa; + return 0; +} diff --git a/krb5-1-7/src/kdc/kdc5_err.et b/krb5-1-7/src/kdc/kdc5_err.et new file mode 100644 index 000000000..9d0ce877c --- /dev/null +++ b/krb5-1-7/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-7/src/kdc/kdc_authdata.c b/krb5-1-7/src/kdc/kdc_authdata.c new file mode 100644 index 000000000..8575caf5b --- /dev/null +++ b/krb5-1-7/src/kdc/kdc_authdata.c @@ -0,0 +1,617 @@ +/* + * kdc/kdc_authdata.c + * + * Copyright (C) 2007 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 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. + * + * AuthorizationData routines for the KDC. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "extern.h" +#include +#include "adm_proto.h" + +#include + +#include +#include "../include/krb5/authdata_plugin.h" + +#if TARGET_OS_MAC +static const char *objdirs[] = { KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/authdata", NULL }; /* should be a list */ +#else +static const char *objdirs[] = { LIBDIR "/krb5/plugins/authdata", NULL }; +#endif + +/* MIT Kerberos 1.6 (V0) authdata plugin callback */ +typedef krb5_error_code (*authdata_proc_0) + (krb5_context, krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_enc_tkt_part * enc_tkt_reply); +/* MIT Kerberos 1.7 (V1) authdata plugin callback */ +typedef krb5_error_code (*authdata_proc_1) + (krb5_context, unsigned int flags, + krb5_db_entry *client, krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); +typedef krb5_error_code (*init_proc) + (krb5_context, void **); +typedef void (*fini_proc) + (krb5_context, void *); + +/* Internal authdata system for copying TGS-REQ authdata to ticket */ +static krb5_error_code handle_request_authdata + (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); + +/* Internal authdata system for handling KDC-issued authdata */ +static krb5_error_code handle_tgt_authdata + (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); + +typedef struct _krb5_authdata_systems { + const char *name; +#define AUTHDATA_SYSTEM_UNKNOWN -1 +#define AUTHDATA_SYSTEM_V0 0 +#define AUTHDATA_SYSTEM_V1 1 + int type; +#define AUTHDATA_FLAG_CRITICAL 0x1 + int flags; + void *plugin_context; + init_proc init; + fini_proc fini; + union { + authdata_proc_1 v1; + authdata_proc_0 v0; + } handle_authdata; +} krb5_authdata_systems; + +static krb5_authdata_systems static_authdata_systems[] = { + { "tgs_req", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_request_authdata } }, + { "tgt", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_tgt_authdata } }, +}; + +static krb5_authdata_systems *authdata_systems; +static int n_authdata_systems; +static struct plugin_dir_handle authdata_plugins; + +/* Load both v0 and v1 authdata plugins */ +krb5_error_code +load_authdata_plugins(krb5_context context) +{ + void **authdata_plugins_ftables_v0 = NULL; + void **authdata_plugins_ftables_v1 = NULL; + size_t module_count; + size_t i, k; + init_proc server_init_proc = NULL; + krb5_error_code code; + + /* Attempt to load all of the authdata plugins we can find. */ + PLUGIN_DIR_INIT(&authdata_plugins); + if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) { + if (krb5int_open_plugin_dirs(objdirs, NULL, + &authdata_plugins, &context->err) != 0) { + return KRB5_PLUGIN_NO_HANDLE; + } + } + + /* Get the method tables provided by the loaded plugins. */ + authdata_plugins_ftables_v0 = NULL; + authdata_plugins_ftables_v1 = NULL; + n_authdata_systems = 0; + + if (krb5int_get_plugin_dir_data(&authdata_plugins, + "authdata_server_1", + &authdata_plugins_ftables_v1, &context->err) != 0 || + krb5int_get_plugin_dir_data(&authdata_plugins, + "authdata_server_0", + &authdata_plugins_ftables_v0, &context->err) != 0) { + code = KRB5_PLUGIN_NO_HANDLE; + goto cleanup; + } + + /* Count the valid modules. */ + module_count = sizeof(static_authdata_systems) + / sizeof(static_authdata_systems[0]); + + if (authdata_plugins_ftables_v1 != NULL) { + struct krb5plugin_authdata_ftable_v1 *ftable; + + for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) { + ftable = authdata_plugins_ftables_v1[i]; + if (ftable->authdata_proc != NULL) + module_count++; + } + } + + if (authdata_plugins_ftables_v0 != NULL) { + struct krb5plugin_authdata_ftable_v0 *ftable; + + for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { + ftable = authdata_plugins_ftables_v0[i]; + if (ftable->authdata_proc != NULL) + module_count++; + } + } + + /* Build the complete list of supported authdata options, and + * leave room for a terminator entry. */ + authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems)); + if (authdata_systems == NULL) { + code = ENOMEM; + goto cleanup; + } + + /* Add the locally-supplied mechanisms to the dynamic list first. */ + for (i = 0, k = 0; + i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]); + i++) { + authdata_systems[k] = static_authdata_systems[i]; + /* Try to initialize the authdata system. If it fails, we'll remove it + * from the list of systems we'll be using. */ + server_init_proc = static_authdata_systems[i].init; + if ((server_init_proc != NULL) && + ((*server_init_proc)(context, &authdata_systems[k].plugin_context) != 0)) { + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + continue; + } + k++; + } + + /* Add dynamically loaded V1 plugins */ + if (authdata_plugins_ftables_v1 != NULL) { + struct krb5plugin_authdata_ftable_v1 *ftable; + + for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) { + krb5_error_code initerr; + void *pctx = NULL; + + ftable = authdata_plugins_ftables_v1[i]; + if ((ftable->authdata_proc == NULL)) { + continue; + } + server_init_proc = ftable->init_proc; + if ((server_init_proc != NULL) && + ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { + const char *emsg; + emsg = krb5_get_error_message(context, initerr); + if (emsg) { + krb5_klog_syslog(LOG_ERR, + "authdata %s failed to initialize: %s", + ftable->name, emsg); + krb5_free_error_message(context, emsg); + } + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + + continue; + } + + authdata_systems[k].name = ftable->name; + authdata_systems[k].type = AUTHDATA_SYSTEM_V1; + authdata_systems[k].init = server_init_proc; + authdata_systems[k].fini = ftable->fini_proc; + authdata_systems[k].handle_authdata.v1 = ftable->authdata_proc; + authdata_systems[k].plugin_context = pctx; + k++; + } + } + + /* Add dynamically loaded V0 plugins */ + if (authdata_plugins_ftables_v0 != NULL) { + struct krb5plugin_authdata_ftable_v0 *ftable; + + for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { + krb5_error_code initerr; + void *pctx = NULL; + + ftable = authdata_plugins_ftables_v0[i]; + if ((ftable->authdata_proc == NULL)) { + continue; + } + server_init_proc = ftable->init_proc; + if ((server_init_proc != NULL) && + ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { + const char *emsg; + emsg = krb5_get_error_message(context, initerr); + if (emsg) { + krb5_klog_syslog(LOG_ERR, + "authdata %s failed to initialize: %s", + ftable->name, emsg); + krb5_free_error_message(context, emsg); + } + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + + continue; + } + + authdata_systems[k].name = ftable->name; + authdata_systems[k].type = AUTHDATA_SYSTEM_V0; + authdata_systems[k].init = server_init_proc; + authdata_systems[k].fini = ftable->fini_proc; + authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc; + authdata_systems[k].plugin_context = pctx; + k++; + } + } + + n_authdata_systems = k; + /* Add the end-of-list marker. */ + authdata_systems[k].name = "[end]"; + authdata_systems[k].type = AUTHDATA_SYSTEM_UNKNOWN; + code = 0; + +cleanup: + if (authdata_plugins_ftables_v1 != NULL) + krb5int_free_plugin_dir_data(authdata_plugins_ftables_v1); + if (authdata_plugins_ftables_v0 != NULL) + krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0); + + return code; +} + +krb5_error_code +unload_authdata_plugins(krb5_context context) +{ + int i; + if (authdata_systems != NULL) { + for (i = 0; i < n_authdata_systems; i++) { + if (authdata_systems[i].fini != NULL) { + (*authdata_systems[i].fini)(context, + authdata_systems[i].plugin_context); + } + memset(&authdata_systems[i], 0, sizeof(authdata_systems[i])); + } + free(authdata_systems); + authdata_systems = NULL; + n_authdata_systems = 0; + krb5int_close_plugin_dirs(&authdata_plugins); + } + return 0; +} + +/* Merge authdata. If copy == 0, in_authdata is invalid on return */ +static krb5_error_code +merge_authdata (krb5_context context, + krb5_authdata **in_authdata, + krb5_authdata ***out_authdata, + krb5_boolean copy) +{ + size_t i, nadata = 0; + krb5_authdata **authdata = *out_authdata; + + if (in_authdata == NULL || in_authdata[0] == NULL) + return 0; + + if (authdata != NULL) { + for (nadata = 0; authdata[nadata] != NULL; nadata++) + ; + } + + for (i = 0; in_authdata[i] != NULL; i++) + ; + + if (authdata == NULL) { + authdata = (krb5_authdata **)calloc(i + 1, sizeof(krb5_authdata *)); + } else { + authdata = (krb5_authdata **)realloc(authdata, + ((nadata + i + 1) * sizeof(krb5_authdata *))); + } + if (authdata == NULL) + return ENOMEM; + + if (copy) { + krb5_error_code code; + krb5_authdata **tmp; + + code = krb5_copy_authdata(context, in_authdata, &tmp); + if (code != 0) + return code; + + in_authdata = tmp; + } + + for (i = 0; in_authdata[i] != NULL; i++) + authdata[nadata + i] = in_authdata[i]; + + authdata[nadata + i] = NULL; + + free(in_authdata); + + *out_authdata = authdata; + + return 0; +} + +/* Handle copying TGS-REQ authorization data into reply */ +static krb5_error_code +handle_request_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code code; + krb5_data scratch; + + if (request->msg_type != KRB5_TGS_REQ || + request->authorization_data.ciphertext.data == NULL) + return 0; + + assert(enc_tkt_request != NULL); + + scratch.length = request->authorization_data.ciphertext.length; + scratch.data = malloc(scratch.length); + if (scratch.data == NULL) + return ENOMEM; + + code = krb5_c_decrypt(context, + enc_tkt_request->session, + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, + 0, &request->authorization_data, + &scratch); + if (code != 0) + code = krb5_c_decrypt(context, + client_key, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, + 0, &request->authorization_data, + &scratch); + + if (code != 0) { + free(scratch.data); + return code; + } + + /* scratch now has the authorization data, so we decode it, and make + * it available to subsequent authdata plugins */ + code = decode_krb5_authdata(&scratch, &request->unenc_authdata); + if (code != 0) { + free(scratch.data); + return code; + } + + free(scratch.data); + + code = merge_authdata(context, request->unenc_authdata, + &enc_tkt_reply->authorization_data, TRUE /* copy */); + + return code; +} + +/* Handle backend-managed authorization data */ +static krb5_error_code +handle_tgt_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code code; + krb5_authdata **db_authdata = NULL; + krb5_db_entry ad_entry; + int ad_nprincs = 0; + krb5_boolean tgs_req = (request->msg_type == KRB5_TGS_REQ); + krb5_const_principal actual_client; + + /* + * Check whether KDC issued authorization data should be included. + * A server can explicitly disable the inclusion of authorization + * data by setting the KRB5_KDB_NO_AUTH_DATA_REQUIRED flag on its + * principal entry. Otherwise authorization data will be included + * if it was present in the TGT, the client is from another realm + * or protocol transition/constrained delegation was used, or, in + * the AS-REQ case, if the pre-auth data indicated the PAC should + * be present. + * + * We permit sign_authorization_data() to return a krb5_db_entry + * representing the principal associated with the authorization + * data, in case that principal is not local to our realm and we + * need to perform additional checks (such as disabling delegation + * for cross-realm protocol transition below). + */ + if (tgs_req) { + assert(enc_tkt_request != NULL); + + if (isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED)) + return 0; + + if (enc_tkt_request->authorization_data == NULL && + !isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM | KRB5_KDB_FLAGS_S4U)) + return 0; + + assert(enc_tkt_reply->times.authtime == enc_tkt_request->times.authtime); + } else { + if (!isflagset(flags, KRB5_KDB_FLAG_INCLUDE_PAC)) + return 0; + } + + /* + * We have this special case for protocol transition, because for + * cross-realm protocol transition the ticket reply client will + * not be changed until the final hop. + */ + if (isflagset(flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + actual_client = for_user_princ; + else + actual_client = enc_tkt_reply->client; + + /* + * If the backend does not implement the sign authdata method, then + * just copy the TGT authorization data into the reply, except for + * the constrained delegation case (which requires special handling + * because it will promote untrusted auth data to KDC issued auth + * data; this requires backend-specific code) + * + * Presently this interface does not support using request auth data + * to influence (eg. possibly restrict) the reply auth data. + */ + code = sign_db_authdata(context, + flags, + actual_client, + client, + server, + krbtgt, + client_key, + server_key, /* U2U or server key */ + enc_tkt_reply->times.authtime, + tgs_req ? enc_tkt_request->authorization_data : NULL, + &db_authdata, + &ad_entry, + &ad_nprincs); + if (code == KRB5_KDB_DBTYPE_NOSUP) { + assert(ad_nprincs == 0); + assert(db_authdata == NULL); + + if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + return KRB5KDC_ERR_POLICY; + + if (tgs_req) + return merge_authdata(context, enc_tkt_request->authorization_data, + &enc_tkt_reply->authorization_data, TRUE); + else + return 0; + } + + if (ad_nprincs != 0) { + if (isflagset(flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) && + isflagset(ad_entry.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) + clear(enc_tkt_reply->flags, TKT_FLG_FORWARDABLE); + + krb5_db_free_principal(context, &ad_entry, ad_nprincs); + + if (ad_nprincs != 1) { + if (db_authdata != NULL) + krb5_free_authdata(context, db_authdata); + return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + } + } + + if (db_authdata != NULL) { + code = merge_authdata(context, db_authdata, + &enc_tkt_reply->authorization_data, + FALSE); + if (code != 0) + krb5_free_authdata(context, db_authdata); + } + + return code; +} + +krb5_error_code +handle_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code code = 0; + int i; + + for (i = 0; i < n_authdata_systems; i++) { + const krb5_authdata_systems *asys = &authdata_systems[i]; + + switch (asys->type) { + case AUTHDATA_SYSTEM_V0: + /* V0 was only in AS-REQ code path */ + if (request->msg_type != KRB5_AS_REQ) + continue; + + code = (*asys->handle_authdata.v0)(context, client, req_pkt, + request, enc_tkt_reply); + break; + case AUTHDATA_SYSTEM_V1: + code = (*asys->handle_authdata.v1)(context, flags, + client, server, krbtgt, + client_key, server_key, + req_pkt, request, for_user_princ, + enc_tkt_request, + enc_tkt_reply); + break; + default: + code = 0; + break; + } + if (code != 0) { + const char *emsg; + + emsg = krb5_get_error_message (context, code); + krb5_klog_syslog (LOG_INFO, + "authdata (%s) handling failure: %s", + asys->name, emsg); + krb5_free_error_message (context, emsg); + + if (asys->flags & AUTHDATA_FLAG_CRITICAL) + break; + } + } + + return code; +} + diff --git a/krb5-1-7/src/kdc/kdc_preauth.c b/krb5-1-7/src/kdc/kdc_preauth.c new file mode 100644 index 000000000..cc7ae34ed --- /dev/null +++ b/krb5-1-7/src/kdc/kdc_preauth.c @@ -0,0 +1,3167 @@ +/* + * kdc/kdc_preauth.c + * + * Copyright 1995, 2003, 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. + * + * 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. + */ +/* + * Copyright (c) 2006-2008, 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" +#include "kdc_util.h" +#include "extern.h" +#include +#include "adm_proto.h" +#if APPLE_PKINIT +#include "pkinit_server.h" +#include "pkinit_cert_store.h" +#endif /* APPLE_PKINIT */ + +#include + +#include +#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_enc_ts + (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_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); + +#if APPLE_PKINIT +/* PKINIT preauth support */ +static krb5_error_code get_pkinit_edata( + 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_module_context, + krb5_pa_data *pa_data); +static krb5_error_code verify_pkinit_request( + 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 *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 return_pkinit_response( + 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 get_entry_data, + void *pa_module_context, + void **pa_request_context); +#endif /* APPLE_PKINIT */ + +static krb5_preauth_systems static_preauth_systems[] = { +#if APPLE_PKINIT + { + "pkinit", + KRB5_PADATA_PK_AS_REQ, + PA_SUFFICIENT, + NULL, /* pa_sys_context */ + NULL, /* init */ + NULL, /* fini */ + get_pkinit_edata, + verify_pkinit_request, + return_pkinit_response, + NULL /* free_pa_request_context */ + }, +#endif /* APPLE_PKINIT */ + { + "timestamp", + KRB5_PADATA_ENC_TIMESTAMP, + 0, + NULL, + NULL, + NULL, + get_enc_ts, + verify_enc_timestamp, + 0 + }, + { + "FAST", + KRB5_PADATA_FX_FAST, + PA_HARDWARE, + NULL, + NULL, + NULL, + NULL, + NULL, + 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 + }, + { + "pac-request", + KRB5_PADATA_PAC_REQUEST, + PA_PSEUDO, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, +#if 0 + { + "server-referral", + KRB5_PADATA_SERVER_REFERRAL, + PA_PSEUDO, + 0, + 0, + return_server_referral + }, +#endif + { "[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) +{ + void **preauth_plugins_ftables; + struct krb5plugin_preauth_server_ftable_v1 *ftable; + size_t module_count, i, j, k; + void *plugin_context; + preauth_server_init_proc server_init_proc = NULL; + char **kdc_realm_names = NULL; + + /* 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, &context->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, &context->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 < (size_t)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, *mkey_ptr; + krb5_key_data *entry_key; + krb5_error_code error; + struct kdc_request_state *state = request->kdc_state; + + 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); + if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing the mkey list in case it's been updated */ + if (krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(context, master_keylist); + master_keylist = tmp_mkey_list; + if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, + &mkey_ptr))) { + free(ret); + return (error); + } + } else { + free(ret); + return (error); + } + } + 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, mkey_ptr, + 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; + case krb5plugin_preauth_fast_armor: + ret = calloc(1, sizeof(krb5_data)); + if (ret == NULL) + return ENOMEM; + if (state->armor_key == NULL) { + *result = ret; + return 0; + } + error = krb5_copy_keyblock(context, state->armor_key, &keys); + if (error == 0) { + ret->data = (char *) keys; + ret->length = sizeof(krb5_keyblock); + *result = ret; + return 0; + } + free(ret); + return error; + case krb5plugin_preauth_free_fast_armor: + if ((*result)->data) { + keys = (krb5_keyblock *) (*result)->data; + krb5_free_keyblock(context, keys); + } + free(*result); + return 0; + 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); + /* Allocate two extra entries for the cookie and the terminator. */ + pa_data = calloc(n_preauth_systems + 2, sizeof(krb5_pa_data *)); + if (pa_data == 0) + return; + 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" : ""); + } +/* If we fail to get the cookie it is probably still reasonable to continue with the response*/ + kdc_preauth_get_cookie(request->kdc_state, pa); + retval = encode_krb5_padata_sequence(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; we may return PREAUTH_REQUIRED later, + but we did not actually fail to verify the pre-auth. */ + if (!pa_found) + return 0; + + + /* The following switch statement allows us + * to return some preauth system errors back to the client. + */ + switch(retval) { + case 0: /* in case of PA-PAC-REQUEST with no PA-ENC-TIMESTAMP */ + 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 get_enc_ts + (krb5_context context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data_proc, + void *pa_system_context, + krb5_pa_data *data) +{ + struct kdc_request_state *state = request->kdc_state; + if (state->armor_key) + return ENOENT; + 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, *mkey_ptr; + krb5_key_data * client_key; + krb5_int32 start; + krb5_timestamp timenow; + krb5_error_code decrypt_err = 0; + + scratch.data = (char *)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; + + if ((retval = krb5_dbe_find_mkey(context, master_keylist, client, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing the mkey list in case it's been updated */ + if (krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(context, master_keylist); + master_keylist = tmp_mkey_list; + if ((retval = krb5_dbe_find_mkey(context, master_keylist, client, + &mkey_ptr))) { + goto cleanup; + } + } else { + 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, mkey_ptr, + 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_principal client_princ, 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, client_princ, 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)); + retval = _make_etype_info_entry(context, client->princ, client_key, + db_etype, &entry[i], etype_info2); + if (retval != 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)) { + retval = _make_etype_info_entry(context, client->princ, + client_key, db_etype, + &entry[i], etype_info2); + if (retval != 0) + goto cleanup; + entry[i+1] = 0; + i++; + } + seen_des++; + } + } + if (etype_info2) + retval = encode_krb5_etype_info2(entry, &scratch); + else + retval = encode_krb5_etype_info(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, client->princ, client_key, + encrypting_key->enctype, entry, + etype_info2); + if (retval) + goto cleanup; + + if (etype_info2) + retval = encode_krb5_etype_info2(entry, &scratch); + else + retval = encode_krb5_etype_info(entry, &scratch); + + if (retval) + goto cleanup; + tmp_padata->contents = (krb5_octet *)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 = (char *)in_padata->contents; + scratch.length = in_padata->length; + + if ((retval = decode_krb5_sam_response(&scratch, &sr))) { + kdc_err(context, 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))) { + kdc_err(context, retval, + "return_sam_data(): decrypt track_id failed"); + free(scratch.data); + goto cleanup; + } + } + + if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) { + kdc_err(context, 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) { + kdc_err(context, 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: + kdc_err(context, 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, *mkey_ptr; + 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) { + kdc_err(kdc_context, 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 = 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! */ + { + if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing the mkey list in case it's been updated */ + if (krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(context, master_keylist); + master_keylist = tmp_mkey_list; + if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, + &mkey_ptr))) { + return (retval); + } + } else { + return (retval); + } + } + + /* 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); + kdc_err(kdc_context, 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, + mkey_ptr, + assoc_key, &encrypting_key, + NULL); + if (retval) { + kdc_err(kdc_context, 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 = (krb5_octet *)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 */ + kdc_err(kdc_context, 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) { + kdc_err(kdc_context, 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) + kdc_err(kdc_context, 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))) { + kdc_err(kdc_context, 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 = (krb5_octet *)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 = (char *)pa->contents; + scratch.length = pa->length; + + if ((retval = decode_krb5_sam_response(&scratch, &sr))) { + scratch.data = 0; + kdc_err(context, 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))) { + kdc_err(context, retval, "decrypt track_id failed"); + goto cleanup; + } + } + + if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) { + kdc_err(context, 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) { + kdc_err(context, 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) { + kdc_err(context, 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.msghash = NULL; + rep.ctime = psr->stime; + rep.cusec = psr->susec; + retval = krb5_rc_store(kdc_context, kdc_rcache, &rep); + if (retval) { + kdc_err(kdc_context, 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))) { + kdc_err(context, retval, "decrypt nonce_or_ts failed"); + goto cleanup; + } + } + + if ((retval = decode_krb5_enc_sam_response_enc(&scratch, &esre))) { + kdc_err(context, 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) + kdc_err(context, 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; +} + +#if APPLE_PKINIT +/* PKINIT preauth support */ +#define PKINIT_DEBUG 0 +#if PKINIT_DEBUG +#define kdcPkinitDebug(args...) printf(args) +#else +#define kdcPkinitDebug(args...) +#endif + +/* + * get_edata() - our only job is to determine whether this KDC is capable of + * performing PKINIT. We infer that from the presence or absence of any + * KDC signing cert. + */ +static krb5_error_code get_pkinit_edata( + krb5_context context, + krb5_kdc_req *request, + krb5_db_entry *client, + krb5_db_entry *server, + preauth_get_entry_data_proc pkinit_get_entry_data, + void *pa_module_context, + krb5_pa_data *pa_data) +{ + krb5_pkinit_signing_cert_t cert = NULL; + krb5_error_code err = krb5_pkinit_get_kdc_cert(0, NULL, NULL, &cert); + + kdcPkinitDebug("get_pkinit_edata: kdc cert %s\n", err ? "NOT FOUND" : "FOUND"); + if(cert) { + krb5_pkinit_release_cert(cert); + } + return err; +} + +/* + * This is 0 only for testing until the KDC DB contains + * the hash of the client cert + */ +#define REQUIRE_CLIENT_CERT_MATCH 1 + +static krb5_error_code verify_pkinit_request( + 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 *data, + preauth_get_entry_data_proc pkinit_get_entry_data, + void *pa_module_context, + void **pa_request_context, + krb5_data **e_data, + krb5_authdata ***authz_data) +{ + krb5_error_code krtn; + krb5_data pa_data; + krb5_data *der_req = NULL; + krb5_boolean valid_cksum; + char *cert_hash = NULL; + unsigned cert_hash_len; + unsigned key_dex; + unsigned cert_match = 0; + krb5_keyblock decrypted_key, *mkey_ptr; + + /* the data we get from the AS-REQ */ + krb5_timestamp client_ctime = 0; + krb5_ui_4 client_cusec = 0; + krb5_timestamp kdc_ctime = 0; + krb5_int32 kdc_cusec = 0; + krb5_ui_4 nonce = 0; + krb5_checksum pa_cksum; + krb5int_cert_sig_status cert_sig_status; + krb5_data client_cert = {0, 0, NULL}; + + krb5_kdc_req *tmp_as_req = NULL; + + kdcPkinitDebug("verify_pkinit_request\n"); + + decrypted_key.contents = NULL; + pa_data.data = (char *)data->contents; + pa_data.length = data->length; + krtn = krb5int_pkinit_as_req_parse(context, &pa_data, + &client_ctime, &client_cusec, + &nonce, &pa_cksum, + &cert_sig_status, + NULL, NULL, /* num_cms_types, cms_types */ + &client_cert, /* signer_cert */ + /* remaining fields unused (for now) */ + NULL, NULL, /* num_all_certs, all_certs */ + NULL, NULL, /* num_trusted_CAs, trusted_CAs */ + NULL); /* kdc_cert */ + if(krtn) { + kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", + (int)krtn); + return krtn; + } + #if PKINIT_DEBUG + if(cert_sig_status != pki_cs_good) { + kdcPkinitDebug("verify_pkinit_request: cert_sig_status %d\n", + (int)cert_sig_status); + } + #endif /* PKINIT_DEBUG */ + + /* + * Verify signature and cert. + * FIXME: The spec calls for an e-data with error-specific type to be + * returned on error here. TD_TRUSTED_CERTIFIERS + * to be returned to the client here. There is no way for a preauth + * module to pass back e-data to process_as_req at this time. We + * might want to add such capability via an out param to check_padata + * and to its callees. + */ + switch(cert_sig_status) { + case pki_cs_good: + break; + case pki_cs_sig_verify_fail: + /* no e-data */ + krtn = KDC_ERR_INVALID_SIG; + goto cleanup; + case pki_cs_no_root: + case pki_cs_unknown_root: + case pki_cs_untrusted: + /* + * Can't verify to known root. + * e-data TD_TRUSTED_CERTIFIERS + */ + kdcPkinitDebug("verify_pkinit_request: KDC_ERR_CANT_VERIFY_CERTIFICATE\n"); + krtn = KDC_ERR_CANT_VERIFY_CERTIFICATE; + goto cleanup; + case pki_cs_bad_leaf: + case pki_cs_expired: + case pki_cs_not_valid_yet: + /* + * Problems with client cert itself. + * e-data type TD_INVALID_CERTIFICATES + */ + krtn = KDC_ERR_INVALID_CERTIFICATE; + goto cleanup; + case pki_cs_revoked: + /* e-data type TD-INVALID-CERTIFICATES */ + krtn = KDC_ERR_REVOKED_CERTIFICATE; + goto cleanup; + case pki_bad_key_use: + krtn = KDC_ERR_INCONSISTENT_KEY_PURPOSE; + /* no e-data */ + goto cleanup; + case pki_bad_digest: + /* undefined (explicitly!) e-data */ + krtn = KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; + goto cleanup; + case pki_bad_cms: + case pki_cs_other_err: + default: + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + krtn = krb5_us_timeofday(context, &kdc_ctime, &kdc_cusec); + if(krtn) { + goto cleanup; + } + if (labs(kdc_ctime - client_ctime) > context->clockskew) { + kdcPkinitDebug("verify_pkinit_request: clock skew violation client %d svr %d\n", + (int)client_ctime, (int)kdc_ctime); + krtn = KRB5KRB_AP_ERR_SKEW; + 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. + */ + krtn = decode_krb5_as_req(req_pkt, &tmp_as_req); + if(krtn) { + kdcPkinitDebug("decode_krb5_as_req returned %d\n", (int)krtn); + goto cleanup; + } + + /* calculate and compare checksum */ + krtn = encode_krb5_kdc_req_body(tmp_as_req, &der_req); + if(krtn) { + kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); + goto cleanup; + } + krtn = krb5_c_verify_checksum(context, NULL, 0, der_req, + &pa_cksum, &valid_cksum); + if(krtn) { + kdcPkinitDebug("krb5_c_verify_checksum returned %d\n", (int)krtn); + goto cleanup; + } + if(!valid_cksum) { + kdcPkinitDebug("verify_pkinit_request: checksum error\n"); + krtn = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + #if REQUIRE_CLIENT_CERT_MATCH + /* look up in the KDB to ensure correct client/cert binding */ + cert_hash = krb5_pkinit_cert_hash_str(&client_cert); + if(cert_hash == NULL) { + krtn = ENOMEM; + goto cleanup; + } + cert_hash_len = strlen(cert_hash); + if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing the mkey list in case it's been updated */ + if (krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(context, master_keylist); + master_keylist = tmp_mkey_list; + if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, + &mkey_ptr))) { + goto cleanup; + } + } else { + goto cleanup; + } + } + for(key_dex=0; key_dexn_key_data; key_dex++) { + krb5_key_data *key_data = &client->key_data[key_dex]; + kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n", + key_dex, + key_data->key_data_type[0], key_data->key_data_length[0], + key_data->key_data_type[1], key_data->key_data_length[1]); + if(key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_CERTHASH) { + continue; + } + + /* + * Unfortunately this key is stored encrypted even though it's + * not sensitive... + */ + krtn = krb5_dbekd_decrypt_key_data(context, mkey_ptr, + key_data, &decrypted_key, NULL); + if(krtn) { + kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n"); + break; + } + if((decrypted_key.contents != NULL) && + (cert_hash_len == decrypted_key.length) && + !memcmp(decrypted_key.contents, cert_hash, cert_hash_len)) { + cert_match = 1; + break; + } + } + if(decrypted_key.contents) { + krb5_free_keyblock_contents(context, &decrypted_key); + } + if(!cert_match) { + kdcPkinitDebug("verify_pkinit_request: client cert does not match\n"); + krtn = KDC_ERR_CLIENT_NOT_TRUSTED; + goto cleanup; + } + #endif /* REQUIRE_CLIENT_CERT_MATCH */ + krtn = 0; + setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); + +cleanup: + if(pa_cksum.contents) { + free(pa_cksum.contents); + } + if (tmp_as_req) { + krb5_free_kdc_req(context, tmp_as_req); + } + if (der_req) { + krb5_free_data(context, der_req); + } + if(cert_hash) { + free(cert_hash); + } + if(client_cert.data) { + free(client_cert.data); + } + kdcPkinitDebug("verify_pkinit_request: returning %d\n", (int)krtn); + return krtn; +} + +static krb5_error_code return_pkinit_response( + 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 pkinit_get_entry_data, + void *pa_module_context, + void **pa_request_context) +{ + krb5_error_code krtn; + krb5_data pa_data; + krb5_pkinit_signing_cert_t signing_cert = NULL; + krb5_checksum as_req_checksum = {0}; + krb5_data *encoded_as_req = NULL; + krb5int_algorithm_id *cms_types = NULL; + krb5_ui_4 num_cms_types = 0; + + /* the data we get from the AS-REQ */ + krb5_ui_4 nonce = 0; + krb5_data client_cert = {0}; + + /* + * Trusted CA list and specific KC cert optionally obtained via + * krb5int_pkinit_as_req_parse(). All are DER-encoded + * issuerAndSerialNumbers. + */ + krb5_data *trusted_CAs = NULL; + krb5_ui_4 num_trusted_CAs; + krb5_data kdc_cert = {0}; + + if (padata == NULL) { + /* Client has to send us something */ + return 0; + } + + kdcPkinitDebug("return_pkinit_response\n"); + pa_data.data = (char *)padata->contents; + pa_data.length = padata->length; + + /* + * We've already verified; just obtain the fields we need to create a response + */ + krtn = krb5int_pkinit_as_req_parse(context, + &pa_data, + NULL, NULL, &nonce, /* ctime, cusec, nonce */ + NULL, NULL, /* pa_cksum, cert_status */ + &num_cms_types, &cms_types, + &client_cert, /* signer_cert: we encrypt for this */ + /* remaining fields unused (for now) */ + NULL, NULL, /* num_all_certs, all_certs */ + &num_trusted_CAs, &trusted_CAs, + &kdc_cert); + if(krtn) { + kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; + } + if(client_cert.data == NULL) { + kdcPkinitDebug("pa_pk_as_req_parse failed to give a client_cert; aborting.\n"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + if(krb5_pkinit_get_kdc_cert(num_trusted_CAs, trusted_CAs, + (kdc_cert.data ? &kdc_cert : NULL), + &signing_cert)) { + /* + * Since get_pkinit_edata was able to obtain *some* KDC cert, + * this means that we can't satisfy the client's requirement. + * FIXME - particular error status for this? + */ + kdcPkinitDebug("return_pkinit_response: NO appropriate signing cert!\n"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* + * Cook up keyblock for caller and for outgoing AS-REP. + * FIXME how much is known to be valid about encrypting_key? + * Will encrypting_key->enctype always be valid here? Seems that + * if we allow for clients without a shared secret (i.e. preauth + * by PKINIT only) there won't be a valid encrypting_key set up + * here for us. + */ + krb5_free_keyblock_contents(context, encrypting_key); + krb5_c_make_random_key(context, encrypting_key->enctype, encrypting_key); + + /* calculate checksum of incoming AS-REQ */ + krtn = encode_krb5_as_req(request, &encoded_as_req); + if(krtn) { + kdcPkinitDebug("encode_krb5_as_req returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; + } + krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, + encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + encoded_as_req, &as_req_checksum); + if(krtn) { + goto cleanup; + } + + /* + * FIXME: here we assume that the client has one cert - the one that + * signed the AuthPack in the request (and that we therefore obtained from + * krb5int_pkinit_as_req_parse()), and the one we're using to encrypt the + * ReplyKeyPack with here. This may need rethinking. + */ + krtn = krb5int_pkinit_as_rep_create(context, + encrypting_key, &as_req_checksum, signing_cert, TRUE, + &client_cert, + num_cms_types, cms_types, + num_trusted_CAs, trusted_CAs, + (kdc_cert.data ? &kdc_cert : NULL), + &pa_data); + if(krtn) { + kdcPkinitDebug("pa_pk_as_rep_create returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; + } + + *send_pa = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); + if(*send_pa == NULL) { + krtn = ENOMEM; + free(pa_data.data); + goto cleanup; + } + (*send_pa)->magic = KV5M_PA_DATA; + (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP; + (*send_pa)->length = pa_data.length; + (*send_pa)->contents = (krb5_octet *)pa_data.data; + krtn = 0; + + #if PKINIT_DEBUG + fprintf(stderr, "return_pkinit_response: SUCCESS\n"); + fprintf(stderr, "nonce 0x%x enctype %d keydata %02x %02x %02x %02x...\n", + (int)nonce, (int)encrypting_key->enctype, + encrypting_key->contents[0], encrypting_key->contents[1], + encrypting_key->contents[2], encrypting_key->contents[3]); + #endif + +cleanup: + /* all of this was allocd by krb5int_pkinit_as_req_parse() */ + if(signing_cert) { + krb5_pkinit_release_cert(signing_cert); + } + if(cms_types) { + unsigned dex; + krb5int_algorithm_id *alg_id; + + for(dex=0; dexalgorithm.data) { + free(alg_id->algorithm.data); + } + if(alg_id->parameters.data) { + free(alg_id->parameters.data); + } + } + free(cms_types); + } + if(trusted_CAs) { + unsigned dex; + for(dex=0; dexpadata == NULL) { + return retval; + } + + for (padata = request->padata; *padata != NULL; padata++) { + if ((*padata)->pa_type == KRB5_PADATA_PAC_REQUEST) { + data.data = (char *)(*padata)->contents; + data.length = (*padata)->length; + + code = decode_krb5_pa_pac_req(&data, &req); + if (code == 0) { + retval = req->include_pac; + krb5_free_pa_pac_req(context, req); + req = NULL; + } + break; + } + } + + return retval; +} + +krb5_error_code +return_svr_referral_data(krb5_context context, + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart) +{ + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; + + /* This should be initialized and only used for Win2K compat */ + assert(reply_encpart->enc_padata == NULL); + + tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA; + + code = krb5_dbe_lookup_tl_data(context, server, &tl_data); + if (code || tl_data.tl_data_length == 0) + return 0; /* no server referrals to return */ + + pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); + if (pa_data == NULL) + return ENOMEM; + + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; + pa_data->length = tl_data.tl_data_length; + pa_data->contents = malloc(pa_data->length); + if (pa_data->contents == NULL) { + free(pa_data); + return ENOMEM; + } + memcpy(pa_data->contents, tl_data.tl_data_contents, tl_data.tl_data_length); + + reply_encpart->enc_padata = (krb5_pa_data **)calloc(2, sizeof(krb5_pa_data *)); + if (reply_encpart->enc_padata == NULL) { + free(pa_data->contents); + free(pa_data); + return ENOMEM; + } + + reply_encpart->enc_padata[0] = pa_data; + reply_encpart->enc_padata[1] = NULL; + + return 0; +} + +#if 0 +static krb5_error_code return_server_referral(krb5_context context, + krb5_pa_data * padata, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa) +{ + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; + krb5_enc_data enc_data; + krb5_data plain; + krb5_data *enc_pa_data; + + *send_pa = NULL; + + tl_data.tl_data_type = KRB5_TL_SERVER_REFERRAL; + + code = krb5_dbe_lookup_tl_data(context, server, &tl_data); + if (code || tl_data.tl_data_length == 0) + return 0; /* no server referrals to return */ + + plain.length = tl_data.tl_data_length; + plain.data = tl_data.tl_data_contents; + + /* Encrypt ServerReferralData */ + code = krb5_encrypt_helper(context, encrypting_key, + KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA, + &plain, &enc_data); + if (code) + return code; + + /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */ + code = encode_krb5_enc_data(&enc_data, &enc_pa_data); + if (code) { + krb5_free_data_contents(context, &enc_data.ciphertext); + return code; + } + + krb5_free_data_contents(context, &enc_data.ciphertext); + + /* Return PA-SERVER-REFERRAL-DATA */ + pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); + if (pa_data == NULL) { + krb5_free_data(context, enc_pa_data); + return ENOMEM; + } + + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; + pa_data->length = enc_pa_data->length; + pa_data->contents = enc_pa_data->data; + + free(enc_pa_data); /* don't free contents */ + + *send_pa = pa_data; + + return 0; +} +#endif diff --git a/krb5-1-7/src/kdc/kdc_util.c b/krb5-1-7/src/kdc/kdc_util.c new file mode 100644 index 000000000..3662f2359 --- /dev/null +++ b/krb5-1-7/src/kdc/kdc_util.c @@ -0,0 +1,2345 @@ +/* + * kdc/kdc_util.c + * + * Copyright 1990,1991,2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ +/* + * Copyright (c) 2006-2008, 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" +#include "kdc_util.h" +#include "extern.h" +#include +#include +#include +#include "adm.h" +#include "adm_proto.h" +#include + +#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_const_principal princ1, krb5_const_principal princ2) +{ + return krb5_realm_compare(kdc_context, princ1, princ2); +} + +krb5_boolean +is_local_principal(krb5_const_principal princ1) +{ + return krb5_realm_compare(kdc_context, princ1, tgs_server); +} + +/* + * Returns TRUE if the kerberos principal is the name of a Kerberos ticket + * service. + */ +krb5_boolean krb5_is_tgs_principal(krb5_const_principal principal) +{ + if ((krb5_princ_size(kdc_context, principal) > 0) && + data_eq_string (*krb5_princ_component(kdc_context, principal, 0), + KRB5_TGS_NAME)) + 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_pa_data * +find_pa_data(krb5_pa_data **padata, krb5_preauthtype pa_type) +{ +return krb5int_find_pa_data(kdc_context, padata, pa_type); +} + +krb5_error_code +kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from, + krb5_data *pkt, krb5_ticket **ticket, + krb5_db_entry *krbtgt, int *nprincs, + krb5_keyblock **subkey, + krb5_pa_data **pa_tgs_req) +{ + krb5_pa_data * tmppa; + krb5_ap_req * apreq; + krb5_error_code retval; + krb5_authdata **authdata = NULL; + 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; + + *nprincs = 0; + + tmppa = find_pa_data(request->padata, KRB5_PADATA_AP_REQ); + if (!tmppa) + 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. + */ + foreign_server = !is_local_principal(apreq->ticket->server); + + 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, 0, foreign_server, + krbtgt, nprincs, &key, &kvno))) + goto cleanup_auth_context; + /* + * We do not use the KDB keytab because other parts of the TGS need the TGT key. + */ + 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; + + retval = krb5int_find_authdata(kdc_context, + (*ticket)->enc_part2->authorization_data, + authenticator->authorization_data, + KRB5_AUTHDATA_FX_ARMOR, &authdata); + if (retval != 0) + goto cleanup_authenticator; + if (authdata&& authdata[0]) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "ticket valid only as FAST armor"); + retval = KRB5KDC_ERR_POLICY; + krb5_free_authdata(kdc_context, authdata); + goto cleanup_authenticator; + } + krb5_free_authdata(kdc_context, authdata); + + + /* 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 && !find_pa_data(request->padata, KRB5_PADATA_FOR_USER)) { + if (is_local_principal((*ticket)->enc_part2->client)) { + /* 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); + } + } + + if (retval == 0) + *pa_tgs_req = tmppa; +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, unsigned int flags, + krb5_boolean match_enctype, krb5_db_entry *server, + int *nprincs, krb5_keyblock **key, krb5_kvno *kvno) +{ + krb5_error_code retval; + krb5_boolean more, similar; + krb5_key_data * server_key; + krb5_keyblock * mkey_ptr; + + *nprincs = 1; + + retval = krb5_db_get_principal_ext(kdc_context, + ticket->server, + flags, + server, + nprincs, + &more); + if (retval) { + return(retval); + } + if (more) { + return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + } else if (*nprincs != 1) { + char *sname; + + 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); + } + if (server->attributes & KRB5_KDB_DISALLOW_SVR || + server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } + + if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, server, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(kdc_context, master_princ, + &master_keyblock, 0, &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(kdc_context, master_keylist); + master_keylist = tmp_mkey_list; + retval = krb5_db_set_mkey_list(kdc_context, master_keylist); + if (retval) + goto errout; + if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, + server, &mkey_ptr))) { + goto errout; + } + } else { + goto errout; + } + } + + retval = krb5_dbe_find_enctype(kdc_context, server, + match_enctype ? ticket->enc_part.enctype : -1, + -1, (krb5_int32)ticket->enc_part.kvno, + &server_key); + if (retval) + goto errout; + if (!server_key) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } + if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { + retval = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, + server_key, + *key, NULL); + } else + retval = ENOMEM; + retval = krb5_c_enctype_compare(kdc_context, ticket->enc_part.enctype, + (*key)->enctype, &similar); + if (retval) + goto errout; + if (!similar) { + retval = KRB5_KDB_NO_PERMITTED_KEY; + goto errout; + } + (*key)->enctype = ticket->enc_part.enctype; + *kvno = server_key->key_data_kvno; +errout: + if (retval != 0) { + krb5_db_free_principal(kdc_context, server, *nprincs); + *nprincs = 0; + } + + 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; + size_t bufsize; + + /* 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 */ + bufsize = strlen(realm) + strlen(otrans) + 3; + if (bufsize > MAX_REALM_LN) + bufsize = MAX_REALM_LN; + if (!(trans = (char *) malloc(bufsize))) { + 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 < (int)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 (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, current, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + 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 (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if((realm[0] == '/') && trans[0]) { + if (strlcat(trans, " ", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, realm, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + 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 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 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 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); + } + + /* + * A Windows KDC will return KDC_ERR_PREAUTH_REQUIRED instead of + * KDC_ERR_POLICY in the following case: + * + * - KDC_OPT_FORWARDABLE is set in KDCOptions but local + * policy has KRB5_KDB_DISALLOW_FORWARDABLE set for the + * client, and; + * - KRB5_KDB_REQUIRES_PRE_AUTH is set for the client but + * preauthentication data is absent in the request. + * + * Hence, this check most be done after the check for preauth + * data, and is now performed by validate_forwardable(). + */ +#if 0 + /* 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); + } +#endif + + /* 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_CLIENT_REVOKED); + } + + /* 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_MUST_USE_USER2USER); + } + + /* + * Check against local policy + */ + errcode = against_local_policy_as(request, client, server, + kdc_time, status); + if (errcode) + return errcode; + + return 0; +} + +int +validate_forwardable(krb5_kdc_req *request, krb5_db_entry client, + krb5_db_entry server, krb5_timestamp kdc_time, + const char **status) +{ + *status = NULL; + 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); + } else + 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 == (int)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 | KDC_OPT_CANONICALIZE | KDC_OPT_CNAME_IN_ADDL_TKT) +#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) || + !data_eq(*krb5_princ_component(kdc_context, ticket->server, 1), + *krb5_princ_realm(kdc_context, request->server))) { + *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 || + !data_eq_string(request->server->data[0], KRB5_TGS_NAME))) { + *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_MUST_USE_USER2USER); + } + + /* 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++; + } + if (isflagset(request->kdc_options, KDC_OPT_CNAME_IN_ADDL_TKT)) { + if (!request->second_ticket || + !request->second_ticket[st_idx]) { + *status = "NO_2ND_TKT"; + return(KDC_ERR_BADOPTION); + } + 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: + /* + * The client could infer the salt from the principal, but + * might use the wrong principal name if this is an alias. So + * it's more reliable to send an explicit salt. + */ + if ((retval = krb5_principal2salt(context, client, salt))) + return retval; + 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; + } + + snprintf(s, len, "%d etypes {", nktypes); + for (i = 0; i < nktypes; i++) { + snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]); + if (strlen(s) + strlen(stmp) + sizeof("}") > len) + break; + strlcat(s, stmp, len); + } + 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; + } + } + strlcat(s, "...", len); + } + strlcat(s, "}", len); + 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; + } + + snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); + + if (rep->ticket != NULL) { + snprintf(stmp, sizeof(stmp), + " tkt=%ld", (long)rep->ticket->enc_part.enctype); + strlcat(s, stmp, len); + } + + if (rep->ticket != NULL + && rep->ticket->enc_part2 != NULL + && rep->ticket->enc_part2->session != NULL) { + snprintf(stmp, sizeof(stmp), " ses=%ld", + (long)rep->ticket->enc_part2->session->enctype); + strlcat(s, stmp, len); + } + strlcat(s, "}", len); + return; +} + +krb5_error_code +get_principal_locked (krb5_context kcontext, + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, + krb5_boolean *more) +{ + return krb5_db_get_principal (kcontext, search_for, entries, nentries, + more); +} + +krb5_error_code +get_principal (krb5_context kcontext, + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, krb5_boolean *more) +{ + /* Eventually this will be used to manage locking while looking up + principals in the database. */ + return get_principal_locked (kcontext, search_for, entries, nentries, + more); +} + + +krb5_error_code +sign_db_authdata (krb5_context context, + unsigned int flags, + krb5_const_principal client_princ, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_timestamp authtime, + krb5_authdata **tgs_authdata, + krb5_authdata ***ret_authdata, + krb5_db_entry *ad_entry, + int *ad_nprincs) +{ + krb5_error_code code; + kdb_sign_auth_data_req req; + kdb_sign_auth_data_rep rep; + krb5_data req_data; + krb5_data rep_data; + + *ret_authdata = NULL; + memset(ad_entry, 0, sizeof(*ad_entry)); + *ad_nprincs = 0; + + memset(&req, 0, sizeof(req)); + memset(&rep, 0, sizeof(rep)); + + req.flags = flags; + req.client_princ = client_princ; + req.client = client; + req.server = server; + req.krbtgt = krbtgt; + req.client_key = client_key; + req.server_key = server_key; + req.authtime = authtime; + req.auth_data = tgs_authdata; + + rep.entry = ad_entry; + rep.nprincs = 0; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = (void *)&rep; + rep_data.length = sizeof(rep); + + code = krb5_db_invoke(context, + KRB5_KDB_METHOD_SIGN_AUTH_DATA, + &req_data, + &rep_data); + + *ret_authdata = rep.auth_data; + *ad_nprincs = rep.nprincs; + + return code; +} + +static krb5_error_code +verify_s4u2self_checksum(krb5_context context, + krb5_keyblock *key, + krb5_pa_for_user *req) +{ + krb5_error_code code; + int i; + krb5_int32 name_type; + char *p; + krb5_data data; + krb5_boolean valid = FALSE; + + if (!krb5_c_is_keyed_cksum(req->cksum.checksum_type)) { + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + /* + * Checksum is over name type and string components of + * client principal name and auth_package. + */ + data.length = 4; + for (i = 0; i < krb5_princ_size(context, req->user); i++) { + data.length += krb5_princ_component(context, req->user, i)->length; + } + data.length += krb5_princ_realm(context, req->user)->length; + data.length += req->auth_package.length; + + p = data.data = malloc(data.length); + if (data.data == NULL) { + return ENOMEM; + } + + name_type = krb5_princ_type(context, req->user); + p[0] = (name_type >> 0 ) & 0xFF; + p[1] = (name_type >> 8 ) & 0xFF; + p[2] = (name_type >> 16) & 0xFF; + p[3] = (name_type >> 24) & 0xFF; + p += 4; + + for (i = 0; i < krb5_princ_size(context, req->user); i++) { + memcpy(p, krb5_princ_component(context, req->user, i)->data, + krb5_princ_component(context, req->user, i)->length); + p += krb5_princ_component(context, req->user, i)->length; + } + + memcpy(p, krb5_princ_realm(context, req->user)->data, + krb5_princ_realm(context, req->user)->length); + p += krb5_princ_realm(context, req->user)->length; + + memcpy(p, req->auth_package.data, req->auth_package.length); + p += req->auth_package.length; + + code = krb5_c_verify_checksum(context, + key, + KRB5_KEYUSAGE_APP_DATA_CKSUM, + &data, + &req->cksum, + &valid); + + if (code == 0 && valid == FALSE) + code = KRB5KRB_AP_ERR_BAD_INTEGRITY; + + free(data.data); + + return code; +} + +/* + * Protocol transition validation code based on AS-REQ + * validation code + */ +static int +validate_s4u2self_request(krb5_kdc_req *request, + const krb5_db_entry *client, + krb5_timestamp kdc_time, + const char **status) +{ + int errcode; + krb5_db_entry server = { 0 }; + + /* The client must not be expired */ + if (client->expiration && client->expiration < kdc_time) { + *status = "CLIENT EXPIRED"; + return KDC_ERR_NAME_EXP; + } + + /* 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) { + *status = "CLIENT KEY EXPIRED"; + return KDC_ERR_KEY_EXP; + } + + /* + * If the client requires password changing, then return an + * error; S4U2Self cannot be used to change a password. + */ + if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PWCHANGE)) { + *status = "REQUIRED PWCHANGE"; + return KDC_ERR_KEY_EXP; + } + + /* 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 against local policy + */ + errcode = against_local_policy_as(request, *client, server, + kdc_time, status); + if (errcode) + return errcode; + + return 0; +} + +/* + * Protocol transition (S4U2Self) + */ +krb5_error_code +kdc_process_s4u2self_req(krb5_context context, + krb5_kdc_req *request, + krb5_const_principal client_princ, + const krb5_db_entry *server, + krb5_keyblock *subkey, + krb5_timestamp kdc_time, + krb5_pa_for_user **for_user, + krb5_db_entry *princ, + int *nprincs, + const char **status) +{ + krb5_error_code code; + krb5_pa_data **pa_data; + krb5_data req_data; + krb5_boolean more; + + *nprincs = 0; + memset(princ, 0, sizeof(*princ)); + + if (request->padata == NULL) { + return 0; + } + + for (pa_data = request->padata; *pa_data != NULL; pa_data++) { + if ((*pa_data)->pa_type == KRB5_PADATA_FOR_USER) + break; + } + if (*pa_data == NULL) { + return 0; + } + +#if 0 + /* + * Ignore request if the server principal is a TGS, not so much + * to avoid unconstrained tickets being issued (as that would + * require knowing the TGS key anyway) but so that we do not + * block the server referral path. + */ + if (krb5_is_tgs_principal(server->princ)) { + return 0; + } +#endif + + *status = "PROCESS_S4U2SELF_REQUEST"; + + req_data.length = (*pa_data)->length; + req_data.data = (char *)(*pa_data)->contents; + + code = decode_krb5_pa_for_user(&req_data, for_user); + if (code) { + return code; + } + + if (krb5_princ_type(context, (*for_user)->user) != + KRB5_NT_ENTERPRISE_PRINCIPAL) { + *status = "INVALID_S4U2SELF_REQUEST"; + return KRB5KDC_ERR_POLICY; + } + + code = verify_s4u2self_checksum(context, subkey, *for_user); + if (code) { + *status = "INVALID_S4U2SELF_CHECKSUM"; + krb5_free_pa_for_user(kdc_context, *for_user); + *for_user = NULL; + return code; + } + if (!krb5_principal_compare_flags(context, request->server, client_princ, + KRB5_PRINCIPAL_COMPARE_ENTERPRISE)) { + *status = "INVALID_S4U2SELF_REQUEST"; + return KRB5KDC_ERR_POLICY; + } + + /* + * Protocol transition is mutually exclusive with renew/forward/etc + * as well as user-to-user and constrained delegation. + * + * We can assert from this check that the header ticket was a TGT, as + * that is validated previously in validate_tgs_request(). + */ + if (request->kdc_options & (NO_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)) { + return KRB5KDC_ERR_BADOPTION; + } + + /* + * Do not attempt to lookup principals in foreign realms. + */ + if (is_local_principal((*for_user)->user)) { + *nprincs = 1; + code = krb5_db_get_principal_ext(kdc_context, + (*for_user)->user, + KRB5_KDB_FLAG_INCLUDE_PAC, + princ, nprincs, &more); + if (code) { + *status = "LOOKING_UP_S4U2SELF_PRINCIPAL"; + *nprincs = 0; + return code; /* caller can free for_user */ + } + + if (more) { + *status = "NON_UNIQUE_S4U2SELF_PRINCIPAL"; + return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + } else if (*nprincs != 1) { + *status = "UNKNOWN_S4U2SELF_PRINCIPAL"; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + } + + code = validate_s4u2self_request(request, princ, kdc_time, status); + if (code) { + return code; + } + } + + *status = NULL; + + return 0; +} + +static krb5_error_code +check_allowed_to_delegate_to(krb5_context context, + const krb5_db_entry *server, + krb5_const_principal proxy) +{ + kdb_check_allowed_to_delegate_req req; + krb5_data req_data; + krb5_data rep_data; + krb5_error_code code; + + /* Can't get a TGT (otherwise it would be unconstrained delegation) */ + if (krb5_is_tgs_principal(proxy)) { + return KRB5KDC_ERR_POLICY; + } + + /* Must be in same realm */ + if (!krb5_realm_compare(context, server->princ, proxy)) { + return KRB5KDC_ERR_BADOPTION; + } + + req.server = server; + req.proxy = proxy; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = NULL; + rep_data.length = 0; + + code = krb5_db_invoke(context, + KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE, + &req_data, + &rep_data); + if (code == KRB5_KDB_DBTYPE_NOSUP) { + code = KRB5KDC_ERR_POLICY; + } + + assert(rep_data.length == 0); + + return code; +} + +krb5_error_code +kdc_process_s4u2proxy_req(krb5_context context, + krb5_kdc_req *request, + const krb5_enc_tkt_part *t2enc, + const krb5_db_entry *server, + krb5_const_principal server_princ, + krb5_const_principal proxy_princ, + const char **status) +{ + krb5_error_code errcode; + + /* + * Constrained delegation is mutually exclusive with renew/forward/etc. + * We can assert from this check that the header ticket was a TGT, as + * that is validated previously in validate_tgs_request(). + */ + if (request->kdc_options & (NO_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)) { + return KRB5KDC_ERR_BADOPTION; + } + + /* Ensure that evidence ticket server matches TGT client */ + if (!krb5_principal_compare(kdc_context, + server->princ, /* after canon */ + server_princ)) { + return KRB5KDC_ERR_SERVER_NOMATCH; + } + + if (!isflagset(t2enc->flags, TKT_FLG_FORWARDABLE)) { + *status = "EVIDENCE_TKT_NOT_FORWARDABLE"; + return KRB5_TKT_NOT_FORWARDABLE; + } + + /* Backend policy check */ + errcode = check_allowed_to_delegate_to(kdc_context, + server, proxy_princ); + if (errcode) { + *status = "NOT_ALLOWED_TO_DELEGATE"; + return errcode; + } + + return 0; +} + +krb5_error_code +kdc_check_transited_list(krb5_context context, + const krb5_data *trans, + const krb5_data *realm1, + const krb5_data *realm2) +{ + krb5_error_code code; + kdb_check_transited_realms_req req; + krb5_data req_data; + krb5_data rep_data; + + /* First check using krb5.conf */ + code = krb5_check_transited_list(kdc_context, trans, realm1, realm2); + if (code) + return code; + + memset(&req, 0, sizeof(req)); + + req.tr_contents = trans; + req.client_realm = realm1; + req.server_realm = realm2; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = NULL; + rep_data.length = 0; + + code = krb5_db_invoke(context, + KRB5_KDB_METHOD_CHECK_TRANSITED_REALMS, + &req_data, + &rep_data); + if (code == KRB5_KDB_DBTYPE_NOSUP) { + code = 0; + } + + assert(rep_data.length == 0); + + return code; +} + +krb5_error_code +validate_transit_path(krb5_context context, + krb5_const_principal client, + krb5_db_entry *server, + krb5_db_entry *krbtgt) +{ + /* Incoming */ + if (isflagset(server->attributes, KRB5_KDB_XREALM_NON_TRANSITIVE)) { + return KRB5KDC_ERR_PATH_NOT_ACCEPTED; + } + + /* Outgoing */ + if (isflagset(krbtgt->attributes, KRB5_KDB_XREALM_NON_TRANSITIVE) && + (!krb5_principal_compare(context, server->princ, krbtgt->princ) || + !krb5_realm_compare(context, client, krbtgt->princ))) { + return KRB5KDC_ERR_PATH_NOT_ACCEPTED; + } + + return 0; +} + + +/* Main logging routines for ticket requests. + + There are a few simple cases -- unparseable requests mainly -- + where messages are logged otherwise, but once a ticket request can + be decoded in some basic way, these routines are used for logging + the details. */ + +/* "status" is null to indicate success. */ +/* Someday, pass local address/port as well. */ +/* Currently no info about name canonicalization is logged. */ +void +log_as_req(const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg) +{ + const char *fromstring = 0; + char fromstringbuf[70]; + char ktypestr[128]; + const char *cname2 = cname ? cname : ""; + const char *sname2 = sname ? sname : ""; + + fromstring = inet_ntop(ADDRTYPE2FAMILY (from->address->addrtype), + from->address->contents, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; + ktypes2str(ktypestr, sizeof(ktypestr), + request->nktypes, request->ktype); + + if (status == NULL) { + /* success */ + char rep_etypestr[128]; + 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, cname2, sname2); + } else { + /* fail */ + krb5_klog_syslog(LOG_INFO, "AS_REQ (%s) %s: %s: %s for %s%s%s", + ktypestr, fromstring, status, + cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); + } +#if 0 + /* Sun (OpenSolaris) version would probably something like this. + The client and server names passed can be null, unlike in the + logging routines used above. Note that a struct in_addr is + used, but the real address could be an IPv6 address. */ + audit_krb5kdc_as_req(some in_addr *, (in_port_t)from->port, 0, + cname, sname, errcode); +#endif +#if 1 + { + kdb_audit_as_req req; + krb5_data req_data; + krb5_data rep_data; + + memset(&req, 0, sizeof(req)); + + req.request = request; + req.client = client; + req.server = server; + req.authtime = authtime; + req.error_code = errcode; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = NULL; + rep_data.length = 0; + + (void) krb5_db_invoke(kdc_context, + KRB5_KDB_METHOD_AUDIT_AS, + &req_data, + &rep_data); + assert(rep_data.length == 0); + } +#endif +} + +/* Here "status" must be non-null. Error code + KRB5KDC_ERR_SERVER_NOMATCH is handled specially. + + Currently no info about name canonicalization is logged. */ +void +log_tgs_req(const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + const char *cname, const char *sname, const char *altcname, + krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, + const char *status, krb5_error_code errcode, const char *emsg) +{ + char ktypestr[128]; + const char *fromstring = 0; + char fromstringbuf[70]; + char rep_etypestr[128]; + + fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype), + from->address->contents, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; + ktypes2str(ktypestr, sizeof(ktypestr), request->nktypes, request->ktype); + if (!errcode) + rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); + else + rep_etypestr[0] = 0; + + /* Differences: server-nomatch message logs 2nd ticket's client + name (useful), and doesn't log ktypestr (probably not + important). */ + if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { + krb5_klog_syslog(LOG_INFO, + "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s", + ktypestr, + fromstring, status, authtime, + rep_etypestr, + !errcode ? "," : "", + cname ? cname : "", + sname ? sname : "", + errcode ? ", " : "", + errcode ? emsg : ""); + if (s4u_name) { + assert(isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) || + isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)); + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + krb5_klog_syslog(LOG_INFO, + "... PROTOCOL-TRANSITION s4u-client=%s", + s4u_name); + else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + krb5_klog_syslog(LOG_INFO, + "... CONSTRAINED-DELEGATION s4u-client=%s", + s4u_name); + } + } else + krb5_klog_syslog(LOG_INFO, + "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s", + fromstring, status, authtime, + cname ? cname : "", + sname ? sname : "", + altcname ? altcname : ""); + + /* OpenSolaris: audit_krb5kdc_tgs_req(...) or + audit_krb5kdc_tgs_req_2ndtktmm(...) */ + /* ... krb5_db_invoke ... */ +} + +void +log_tgs_alt_tgt(krb5_principal p) +{ + char *sname; + if (krb5_unparse_name(kdc_context, p, &sname)) { + krb5_klog_syslog(LOG_INFO, + "TGS_REQ: issuing alternate TGT"); + } else { + limit_string(sname); + krb5_klog_syslog(LOG_INFO, "TGS_REQ: issuing TGT %s", sname); + free(sname); + } + /* OpenSolaris: audit_krb5kdc_tgs_req_alt_tgt(...) */ +} + diff --git a/krb5-1-7/src/kdc/kdc_util.h b/krb5-1-7/src/kdc/kdc_util.h new file mode 100644 index 000000000..060442604 --- /dev/null +++ b/krb5-1-7/src/kdc/kdc_util.h @@ -0,0 +1,368 @@ +/* + * kdc/kdc_util.h + * + * Portions Copyright (C) 2007 Apple Inc. + * Copyright 1990, 2007 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" +#include "kdb_ext.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_const_principal, krb5_const_principal); +krb5_boolean is_local_principal(krb5_const_principal princ1); +krb5_boolean krb5_is_tgs_principal (krb5_const_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_db_entry *krbtgt, + int *nprincs, + krb5_keyblock **, krb5_pa_data **pa_tgs_req); + +krb5_error_code kdc_get_server_key (krb5_ticket *, unsigned int, + krb5_boolean match_enctype, + krb5_db_entry *, int *, + krb5_keyblock **, krb5_kvno *); + +int validate_as_request (krb5_kdc_req *, krb5_db_entry, + krb5_db_entry, krb5_timestamp, + const char **); + +int validate_forwardable(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); +void kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...); + +/* network.c */ +krb5_error_code listen_and_process (void); +krb5_error_code setup_network (void); +krb5_error_code closedown_network (void); + +/* 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); + +krb5_pa_data *find_pa_data + (krb5_pa_data **padata, krb5_preauthtype pa_type); + +/* kdc_authdata.c */ +krb5_error_code load_authdata_plugins(krb5_context context); +krb5_error_code unload_authdata_plugins(krb5_context context); + +krb5_error_code +handle_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); + +/* 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); + +/* kdc_util.c */ +krb5_error_code +get_principal_locked (krb5_context kcontext, + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, + krb5_boolean *more); +krb5_error_code +get_principal (krb5_context kcontext, + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, krb5_boolean *more); + +krb5_boolean +include_pac_p(krb5_context context, krb5_kdc_req *request); + +krb5_error_code return_svr_referral_data + (krb5_context context, + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart); + +krb5_error_code sign_db_authdata + (krb5_context context, + unsigned int flags, + krb5_const_principal client_princ, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_timestamp authtime, + krb5_authdata **tgs_authdata, + krb5_authdata ***ret_authdata, + krb5_db_entry *ad_entry, + int *ad_nprincs); + +krb5_error_code kdc_process_s4u2self_req + (krb5_context context, + krb5_kdc_req *request, + krb5_const_principal client_princ, + const krb5_db_entry *server, + krb5_keyblock *subkey, + krb5_timestamp kdc_time, + krb5_pa_for_user **s4u2_req, + krb5_db_entry *princ, + int *nprincs, + const char **status); + +krb5_error_code kdc_process_s4u2proxy_req + (krb5_context context, + krb5_kdc_req *request, + const krb5_enc_tkt_part *t2enc, + const krb5_db_entry *server, + krb5_const_principal server_princ, + krb5_const_principal proxy_princ, + const char **status); + +krb5_error_code kdc_check_transited_list + (krb5_context context, + const krb5_data *trans, + const krb5_data *realm1, + const krb5_data *realm2); + +krb5_error_code audit_as_request + (krb5_kdc_req *request, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp authtime, + krb5_error_code errcode); + +krb5_error_code audit_tgs_request + (krb5_kdc_req *request, + krb5_const_principal client, + krb5_db_entry *server, + krb5_timestamp authtime, + krb5_error_code errcode); + +krb5_error_code +validate_transit_path(krb5_context context, + krb5_const_principal client, + krb5_db_entry *server, + krb5_db_entry *krbtgt); + + +void +log_as_req(const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg); +void +log_tgs_req(const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + const char *cname, const char *sname, const char *altcname, + krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, + const char *status, krb5_error_code errcode, const char *emsg); +void log_tgs_alt_tgt(krb5_principal p); + +/*Request state*/ + +struct kdc_request_state { + krb5_keyblock *armor_key; + krb5_keyblock *strengthen_key; + krb5_pa_data *cookie; + krb5_int32 fast_options; + krb5_int32 fast_internal_flags; +}; + +krb5_error_code kdc_make_rstate(struct kdc_request_state **out); +void kdc_free_rstate +(struct kdc_request_state *s); + +/* FAST*/ +enum krb5_fast_kdc_flags { + KRB5_FAST_REPLY_KEY_USED = 0x1, + KRB5_FAST_REPLY_KEY_REPLACED = 0x02, +}; + +krb5_error_code kdc_find_fast +(krb5_kdc_req **requestptr, krb5_data *checksummed_data, + krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session, + struct kdc_request_state *state); + +krb5_error_code kdc_fast_response_handle_padata +(struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_kdc_rep *rep, + krb5_enctype enctype); +krb5_error_code kdc_fast_handle_error +(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_pa_data **in_padata, krb5_error *err); + +krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key); + + +krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, + krb5_pa_data **cookie); + + + + +#define isflagset(flagfield, flag) (flagfield & (flag)) +#define setflag(flagfield, flag) (flagfield |= (flag)) +#define clear(flagfield, flag) (flagfield &= ~(flag)) + +#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-7/src/kdc/krb5kdc.M b/krb5-1-7/src/kdc/krb5kdc.M new file mode 100644 index 000000000..80e232023 --- /dev/null +++ b/krb5-1-7/src/kdc/krb5kdc.M @@ -0,0 +1,168 @@ +.\" kdc/krb5kdc.M +.\" +.\" Copyright 1990, 2008 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 \-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= +.fi +specifies the number of connections to be maintained per LDAP server. + +.nf +\-x host= +specifies the LDAP server to connect to by a LDAP URI. + +\-x 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= +.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 to be entered manually +as a password when -m is given; the default is "des-cbc-crc". +.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 \-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-7/src/kdc/main.c b/krb5-1-7/src/kdc/main.c new file mode 100644 index 000000000..126222953 --- /dev/null +++ b/krb5-1-7/src/kdc/main.c @@ -0,0 +1,922 @@ +/* + * kdc/main.c + * + * Copyright 1990,2001,2008,2009 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. + */ +/* + * Copyright (c) 2006-2008, 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 +#include +#include +#include +#include + +#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 +#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 (void); + +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 + +static krb5_context kdc_err_context; +static const char *kdc_progname; + +/* + * We use krb5_klog_init to set up a com_err callback to log error + * messages. The callback also pulls the error message out of the + * context we pass to krb5_klog_init; however, we use realm-specific + * contexts for most of our krb5 library calls, so the error message + * isn't present in the global context. This wrapper ensures that the + * error message state from the call context is copied into the + * context known by krb5_klog. call_context can be NULL if the error + * code did not come from a krb5 library function. + */ +void +kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...) +{ + va_list ap; + + if (call_context) + krb5_copy_error_message(kdc_err_context, call_context); + va_start(ap, fmt); + com_err_va(kdc_progname, code, fmt, ap); + va_end(ap); +} + +/* + * 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; irealm_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_host_based_services) + free(rdp->realm_host_based_services); + if (rdp->realm_no_host_referral) + free(rdp->realm_no_host_referral); + 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) { + /* XXX shouldn't memset be zap for safety? */ + memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length); + free(rdp->realm_mkey.contents); + } + if (rdp->mkey_list) + krb5_dbe_free_key_list(rdp->realm_context, rdp->mkey_list); + 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); +} + +static krb5_error_code +handle_referral_params(krb5_realm_params *rparams, + char *no_refrls, char *host_based_srvcs, + kdc_realm_t *rdp ) +{ + krb5_error_code retval = 0; + if (no_refrls && krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == TRUE) { + rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_no_host_referral) + retval = ENOMEM; + } else { + if (rparams && rparams->realm_no_host_referral) { + if (krb5_match_config_pattern(rparams->realm_no_host_referral, KRB5_CONF_ASTERISK) == TRUE) { + rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_no_host_referral) + retval = ENOMEM; + } else if (no_refrls && (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", + " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0)) + retval = ENOMEM; + else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", + rparams->realm_no_host_referral, " ") < 0) + retval = ENOMEM; + } else if( no_refrls != NULL) { + if ( asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls, " ") < 0) + retval = ENOMEM; + } else + rdp->realm_no_host_referral = NULL; + } + + if (rdp->realm_no_host_referral && krb5_match_config_pattern(rdp->realm_no_host_referral, KRB5_CONF_ASTERISK) == TRUE) { + rdp->realm_host_based_services = NULL; + return 0; + } + + if (host_based_srvcs && (krb5_match_config_pattern(host_based_srvcs, KRB5_CONF_ASTERISK) == TRUE)) { + rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_host_based_services) + retval = ENOMEM; + } else { + if (rparams && rparams->realm_host_based_services) { + if (krb5_match_config_pattern(rparams->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE) { + rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_host_based_services) + retval = ENOMEM; + } else if (host_based_srvcs) { + if (asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s", + " ", host_based_srvcs," ",rparams->realm_host_based_services, " ") < 0) + retval = ENOMEM; + } else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", + rparams->realm_host_based_services, " ") < 0) + retval = ENOMEM; + } else if (host_based_srvcs) { + if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", host_based_srvcs, " ") < 0) + retval = ENOMEM; + } else + rdp->realm_host_based_services = NULL; + } + + return retval; +} +/* + * 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(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, char *no_refrls, + char *host_based_srvcs) +{ + krb5_error_code kret; + krb5_boolean manual; + krb5_realm_params *rparams; + int kdb_open_flags; + krb5_kvno mkvno = IGNORE_VNO; + + 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) { + kdc_err(NULL, kret, "while getting context for realm %s", realm); + goto whoops; + } + + kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name, + &rparams); + if (kret) { + kdc_err(rdp->realm_context, kret, "while reading realm parameters"); + goto whoops; + } + + /* Handle profile file name */ + if (rparams && rparams->realm_profile) { + rdp->realm_profile = strdup(rparams->realm_profile); + if (!rdp->realm_profile) { + kret = ENOMEM; + goto whoops; + } + } + + /* 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); + if (!rdp->realm_mpname) { + kret = ENOMEM; + goto whoops; + } + + /* 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 (!rdp->realm_ports) { + kret = ENOMEM; + goto whoops; + } + 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); + if (!rdp->realm_tcp_ports) { + kret = ENOMEM; + goto whoops; + } + /* Handle stash file */ + if (rparams && rparams->realm_stash_file) { + rdp->realm_stash = strdup(rparams->realm_stash_file); + if (!rdp->realm_stash) { + kret = ENOMEM; + goto whoops; + } + 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; + + /* Handle KDC referrals */ + kret = handle_referral_params(rparams, no_refrls, host_based_srvcs, rdp); + if (kret == ENOMEM) + goto whoops; + + 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))) { + kdc_err(rdp->realm_context, kret, "while setting default realm to %s", + realm); + goto whoops; + } + + /* first open the database before doing anything */ + if (kdc_modifies_kdb) + kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC; + else + kdb_open_flags = KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC; + if ((kret = krb5_db_open(rdp->realm_context, db_args, kdb_open_flags))) { + kdc_err(rdp->realm_context, 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))) { + kdc_err(rdp->realm_context, kret, + "while setting up master key name %s for realm %s", + rdp->realm_mpname, realm); + goto whoops; + } + + /* + * Get the master key (note, may not be the most current mkey). + */ + if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, + rdp->realm_mkey.enctype, manual, + FALSE, rdp->realm_stash, + &mkvno, NULL, &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + "while fetching master key %s for realm %s", + rdp->realm_mpname, realm); + goto whoops; + } +#if 0 /************** Begin IFDEF'ed OUT *******************************/ + /* + * Commenting krb5_db_verify_master_key out because it requires the most + * current mkey which may not be the case here. The call to + * krb5_db_fetch_mkey_list() will end up verifying that the mkey is viable + * anyway. + */ + /* Verify the master key */ + if ((kret = krb5_db_verify_master_key(rdp->realm_context, + rdp->realm_mprinc, + IGNORE_VNO, + &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + "while verifying master key for realm %s", realm); + goto whoops; + } +#endif /**************** END IFDEF'ed OUT *******************************/ + + if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc, + &rdp->realm_mkey, mkvno, &rdp->mkey_list))) { + kdc_err(rdp->realm_context, kret, + "while fetching master keys list for realm %s", realm); + goto whoops; + } + + if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + "while setting master key for realm %s", realm); + goto whoops; + } + kret = krb5_db_set_mkey_list(rdp->realm_context, rdp->mkey_list); + if (kret) { + kdc_err(rdp->realm_context, kret, + "while setting master key list for realm %s", realm); + goto whoops; + } + + /* Set up the keytab */ + if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, + &rdp->realm_keytab))) { + kdc_err(rdp->realm_context, 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))) { + kdc_err(rdp->realm_context, kret, + "while building TGS name for realm %s", realm); + goto whoops; + } + + if (!rkey_init_done) { + krb5_data seed; + /* + * If all that worked, then initialize the random key + * generators. + */ + + seed.length = rdp->realm_mkey.length; + seed.data = (char *)rdp->realm_mkey.contents; + + if ((kret = krb5_c_random_add_entropy(rdp->realm_context, + KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) + goto whoops; + + 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]\n\t\t[-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname]\n\t\t[-p port] [-n]\n" + "\nwhere,\n\t[-x db_args]* - Any number of database specific arguments. Look at\n" + "\t\t\teach database module documentation for supported\n\t\t\targuments\n", + name); + return; +} + +char **db_args = NULL; +void +initialize_realms(krb5_context kcontext, int argc, char **argv) +{ + int c; + char *db_name = (char *) NULL; + char *lrealm = (char *) NULL; + char *mkey_name = (char *) NULL; + char *rcname = KDCRCACHE; + krb5_error_code retval; + krb5_enctype menctype = ENCTYPE_UNKNOWN; + kdc_realm_t *rdatap = NULL; + krb5_boolean manual = FALSE; + char *default_udp_ports = 0; + char *default_tcp_ports = 0; + krb5_pointer aprof; + const char *hierarchy[3]; + char *no_refrls = NULL; + char *host_based_srvcs = NULL; + int db_args_size = 0; + + extern char *optarg; + + if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { + hierarchy[0] = KRB5_CONF_KDCDEFAULTS; + hierarchy[1] = KRB5_CONF_KDC_PORTS; + hierarchy[2] = (char *) NULL; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) + default_udp_ports = 0; + hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) + default_tcp_ports = 0; + hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE; + if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) + max_dgram_reply_size = MAX_DGRAM_SIZE; + hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL; + if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)) + no_refrls = 0; + if (!no_refrls || krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) { + hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES; + if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) + host_based_srvcs = 0; + } + + /* 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_udp_ports == 0) { + fprintf(stderr," KDC cannot initialize. Not enough memory\n"); + exit(1); + } + } + if (default_tcp_ports == 0) { + default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST); + if (default_tcp_ports == 0) { + fprintf(stderr," KDC cannot initialize. Not enough memory\n"); + exit(1); + } + } + + /* + * 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(rdatap, optarg, mkey_name, + menctype, default_udp_ports, + default_tcp_ports, manual, db_args, + no_refrls, host_based_srvcs))) { + 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 ) { + if (asprintf(&db_name, "dbname=%s", optarg) < 0) { + fprintf(stderr, + "%s: KDC cannot initialize. Not enough memory\n", + argv[0]); + exit(1); + } + } + + 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 (!default_udp_ports) { + fprintf(stderr," KDC cannot initialize. Not enough memory\n"); + exit(1); + } +#if 0 /* not yet */ + if (default_tcp_ports) + free(default_tcp_ports); + default_tcp_ports = strdup(optarg); +#endif + break; + case '4': + break; + case 'X': + break; + case '?': + default: + usage(argv[0]); + exit(1); + } + } + + /* + * 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(rdatap, lrealm, mkey_name, menctype, + default_udp_ports, default_tcp_ports, + manual, db_args, no_refrls, + host_based_srvcs))) { + 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); + if (host_based_srvcs) + free(host_based_srvcs); + if (no_refrls) + free(no_refrls); + + return; +} + +void +finish_realms() +{ + 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); + kdc_err_context = kcontext; + kdc_progname = argv[0]; + /* N.B.: After this point, com_err sends output to the KDC log + file, and not to stderr. We use the kdc_err wrapper around + com_err to ensure that the error state exists in the context + known to the krb5_klog callback. */ + + initialize_kdc5_error_table(); + + /* + * Scan through the argument list + */ + initialize_realms(kcontext, argc, argv); + + setup_signal_handlers(); + + load_preauth_plugins(kcontext); + load_authdata_plugins(kcontext); + + retval = setup_sam(); + if (retval) { + kdc_err(kcontext, retval, "while initializing SAM"); + finish_realms(); + return 1; + } + + if ((retval = setup_network())) { + kdc_err(kcontext, retval, "while initializing network"); + finish_realms(); + return 1; + } + if (!nofork && daemon(0, 0)) { + kdc_err(kcontext, errno, "while detaching from tty"); + finish_realms(); + return 1; + } + krb5_klog_syslog(LOG_INFO, "commencing operation"); + if ((retval = listen_and_process())) { + kdc_err(kcontext, retval, "while processing network requests"); + errout++; + } + if ((retval = closedown_network())) { + kdc_err(kcontext, retval, "while shutting down network"); + errout++; + } + krb5_klog_syslog(LOG_INFO, "shutting down"); + unload_preauth_plugins(kcontext); + unload_authdata_plugins(kcontext); + krb5_klog_close(kdc_context); + finish_realms(); + 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-7/src/kdc/migration.doc b/krb5-1-7/src/kdc/migration.doc new file mode 100644 index 000000000..d3613ac0d --- /dev/null +++ b/krb5-1-7/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-7/src/kdc/network.c b/krb5-1-7/src/kdc/network.c new file mode 100644 index 000000000..20175efbf --- /dev/null +++ b/krb5-1-7/src/kdc/network.c @@ -0,0 +1,1679 @@ +/* + * kdc/network.c + * + * Copyright 1990,2000,2007,2008,2009 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 "kdc_util.h" +#include "extern.h" +#include "kdc5_err.h" +#include "adm_proto.h" +#include +#include + +#include +#include +#include "port-sockets.h" +#include "socket-utils.h" + +#ifdef HAVE_NETINET_IN_H +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +/* for SIOCGIFCONF, etc. */ +#include +#endif +#include +#if HAVE_SYS_SELECT_H +#include +#endif +#include + +#ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */ +#include +#endif + +#ifdef HAVE_SYS_FILIO_H +#include /* 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 + +/* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to + IPV6_PKTINFO for RFC 2292 implementations. */ +#ifndef IPV6_RECVPKTINFO +#define IPV6_RECVPKTINFO IPV6_PKTINFO +#endif +/* Parallel, though not standardized. */ +#ifndef IP_RECVPKTINFO +#define IP_RECVPKTINFO IP_PKTINFO +#endif + +static int +set_pktinfo(int sock, int family) +{ + int sockopt = 1; + int option = 0, proto = 0; + + switch (family) { +#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO) + case AF_INET: + proto = IPPROTO_IP; + option = IP_RECVPKTINFO; + break; +#endif +#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) + case AF_INET6: + proto = IPPROTO_IPV6; + option = IPV6_RECVPKTINFO; + break; +#endif + default: + return EINVAL; + } + if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt))) + return errno; + return 0; +} + + +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)) + strlcpy(buf, "", sizeof(buf)); + 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 conn_type { + CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP, + CONN_ROUTING +}; + +/* Per-connection info. */ +struct connection { + int fd; + enum conn_type type; + void (*service)(struct connection *, int); + union { + /* Type-specific information. */ + 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) \ + (free(set.data), set.data = 0, set.max = 0, set.n = 0) + + +/* Set connections; */ +static SET(struct connection *) connections; +#define n_sockets connections.n +#define conns connections.data + +/* Set 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 { + krb5_error_code retval; + int udp_flags; +#define UDP_DO_IPV4 1 +#define UDP_DO_IPV6 2 +}; + +static struct connection * +add_fd (struct socksetup *data, int sock, enum conn_type conntype, + void (*service)(struct connection *, int)) +{ + struct connection *newconn; + void *tmp; + +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + data->retval = EMFILE; /* XXX */ + kdc_err(NULL, 0, "file descriptor number %d too high", sock); + return 0; + } +#endif + newconn = malloc(sizeof(*newconn)); + if (newconn == 0) { + data->retval = ENOMEM; + kdc_err(NULL, ENOMEM, "cannot allocate storage for connection info"); + return 0; + } + if (!ADD(connections, newconn, tmp)) { + data->retval = ENOMEM; + kdc_err(NULL, ENOMEM, "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 *, int); +static void accept_tcp_connection(struct connection *, int); +static void process_tcp_connection(struct connection *, int); + +static struct connection * +add_udp_fd (struct socksetup *data, int sock, int pktinfo) +{ + return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : 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 const int one = 1; + +static int +setnbio(int sock) +{ + return ioctlsocket(sock, FIONBIO, (const void *)&one); +} + +static int +setkeepalive(int sock) +{ + return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(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) { + kdc_err(NULL, errno, "Cannot create TCP server socket on %s", + paddr(addr)); + return -1; + } + set_cloexec_fd(sock); +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + close(sock); + kdc_err(NULL, 0, "TCP socket fd number %d (for %s) too high", + sock, paddr(addr)); + return -1; + } +#endif + if (setreuseaddr(sock, 1) < 0) + kdc_err(NULL, 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)) + kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", sock); + else + kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); +#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) { + kdc_err(NULL, errno, "Cannot bind TCP server socket on %s", + paddr(addr)); + close(sock); + return -1; + } + if (listen(sock, 5) < 0) { + kdc_err(NULL, errno, "Cannot listen on TCP server socket on %s", + paddr(addr)); + close(sock); + return -1; + } + if (setnbio(sock)) { + kdc_err(NULL, errno, + "cannot set listening tcp socket on %s non-blocking", + paddr(addr)); + close(sock); + return -1; + } + if (setnolinger(sock)) { + kdc_err(NULL, 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) { + if (add_tcp_listener_fd(data, s4) == NULL) + close(s4); + else { + FD_SET(s4, &sstate.rfds); + if (s4 >= sstate.max) + sstate.max = s4 + 1; + krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", + s4, paddr((struct sockaddr *)&sin4)); + } + } +#ifdef KRB5_USE_INET6 + if (s6 >= 0) { + if (add_tcp_listener_fd(data, s6) == NULL) { + close(s6); + s6 = -1; + } else { + FD_SET(s6, &sstate.rfds); + if (s6 >= sstate.max) + sstate.max = s6 + 1; + 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; +} + +#if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)) +union pktinfo { +#ifdef HAVE_STRUCT_IN6_PKTINFO + struct in6_pktinfo pi6; +#endif +#ifdef HAVE_STRUCT_IN_PKTINFO + struct in_pktinfo pi4; +#endif + char c; +}; + +static int +setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, + char *haddrbuf, int pktinfo); + +static void +setup_udp_pktinfo_ports(struct socksetup *data) +{ +#ifdef IP_PKTINFO + { + struct sockaddr_in sa; + int r; + + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + sa.sin_len = sizeof(sa); +#endif + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV4; + } +#endif +#ifdef IPV6_PKTINFO + { + struct sockaddr_in6 sa; + int r; + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; +#ifdef HAVE_SA_LEN + sa.sin6_len = sizeof(sa); +#endif + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV6; + } +#endif +} +#else /* no pktinfo compile-time support */ +static void +setup_udp_pktinfo_ports(struct socksetup *data) +{ +} +#endif + +static int +setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, + char *haddrbuf, int pktinfo) +{ + int sock = -1, i, r; + u_short port; + + FOREACH_ELT (udp_port_data, i, port) { + sock = socket (addr->sa_family, SOCK_DGRAM, 0); + if (sock == -1) { + data->retval = errno; + kdc_err(NULL, data->retval, + "Cannot create server socket for port %d address %s", + port, haddrbuf); + return 1; + } + set_cloexec_fd(sock); +#ifdef KRB5_USE_INET6 + if (addr->sa_family == AF_INET6) { +#ifdef IPV6_V6ONLY + if (setv6only(sock, 1)) + kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", + sock); + else + kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); +#else + krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); +#endif /* IPV6_V6ONLY */ + } +#endif + set_sa_port(addr, htons(port)); + if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) { + data->retval = errno; + kdc_err(NULL, data->retval, + "Cannot bind server socket to port %d address %s", + port, haddrbuf); + close(sock); + return 1; + } +#if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))) + assert(pktinfo == 0); +#endif + if (pktinfo) { + r = set_pktinfo(sock, addr->sa_family); + if (r) { + kdc_err(NULL, r, + "Cannot request packet info for udp socket address %s port %d", + haddrbuf, port); + close(sock); + return 1; + } + } + krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock, + paddr((struct sockaddr *)addr), + pktinfo ? " (pktinfo)" : ""); + if (add_udp_fd (data, sock, pktinfo) == 0) { + close(sock); + return 1; + } + FD_SET (sock, &sstate.rfds); + if (sock >= sstate.max) + sstate.max = sock + 1; + } + return 0; +} + +static int +setup_udp_port(void *P_data, struct sockaddr *addr) +{ + struct socksetup *data = P_data; + char haddrbuf[NI_MAXHOST]; + int err; + + if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4)) + return 0; +#ifdef AF_INET6 + if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6)) + return 0; +#endif + err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf), + 0, 0, NI_NUMERICHOST); + if (err) + strlcpy(haddrbuf, "", sizeof(haddrbuf)); + + 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 +#ifdef AF_APPLETALK + case AF_APPLETALK: + return 0; +#endif + default: + krb5_klog_syslog (LOG_INFO, + "skipping unrecognized local address family %d", + addr->sa_family); + return 0; + } + return setup_udp_port_1(data, addr, haddrbuf, 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 + +static int network_reconfiguration_needed = 0; + +#ifdef HAVE_STRUCT_RT_MSGHDR +#include + +static char *rtm_type_name(int type) +{ + switch (type) { + case RTM_ADD: return "RTM_ADD"; + case RTM_DELETE: return "RTM_DELETE"; + case RTM_NEWADDR: return "RTM_NEWADDR"; + case RTM_DELADDR: return "RTM_DELADDR"; + case RTM_IFINFO: return "RTM_IFINFO"; + case RTM_OLDADD: return "RTM_OLDADD"; + case RTM_OLDDEL: return "RTM_OLDDEL"; + case RTM_RESOLVE: return "RTM_RESOLVE"; +#ifdef RTM_NEWMADDR + case RTM_NEWMADDR: return "RTM_NEWMADDR"; + case RTM_DELMADDR: return "RTM_DELMADDR"; +#endif + case RTM_MISS: return "RTM_MISS"; + case RTM_REDIRECT: return "RTM_REDIRECT"; + case RTM_LOSING: return "RTM_LOSING"; + case RTM_GET: return "RTM_GET"; + default: return "?"; + } +} + +static void process_routing_update(struct connection *conn, int selflags) +{ + int n_read; + struct rt_msghdr rtm; + + krb5_klog_syslog(LOG_INFO, "routing socket readable"); + while ((n_read = read(conn->fd, &rtm, sizeof(rtm))) > 0) { + if (n_read < sizeof(rtm)) { + /* Quick hack to figure out if the interesting + fields are present in a short read. + + A short read seems to be normal for some message types. + Only complain if we don't have the critical initial + header fields. */ +#define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD)) + if (n_read < RS(rtm_type) || + n_read < RS(rtm_version) || + n_read < RS(rtm_msglen)) { + krb5_klog_syslog(LOG_ERR, + "short read (%d/%d) from routing socket", + n_read, (int) sizeof(rtm)); + return; + } + } + krb5_klog_syslog(LOG_INFO, + "got routing msg type %d(%s) v%d", + rtm.rtm_type, rtm_type_name(rtm.rtm_type), + rtm.rtm_version); + if (rtm.rtm_msglen > sizeof(rtm)) { + /* It appears we get a partial message and the rest is + thrown away? */ + } else if (rtm.rtm_msglen != n_read) { + krb5_klog_syslog(LOG_ERR, + "read %d from routing socket but msglen is %d", + n_read, rtm.rtm_msglen); + } + switch (rtm.rtm_type) { + case RTM_ADD: + case RTM_DELETE: + case RTM_NEWADDR: + case RTM_DELADDR: + case RTM_IFINFO: + case RTM_OLDADD: + case RTM_OLDDEL: + krb5_klog_syslog(LOG_INFO, "reconfiguration needed"); + network_reconfiguration_needed = 1; + break; + case RTM_RESOLVE: +#ifdef RTM_NEWMADDR + case RTM_NEWMADDR: + case RTM_DELMADDR: +#endif + case RTM_MISS: + case RTM_REDIRECT: + case RTM_LOSING: + case RTM_GET: + /* Not interesting. */ + krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting"); + break; + default: + krb5_klog_syslog(LOG_INFO, "unhandled routing message type, will reconfigure just for the fun of it"); + network_reconfiguration_needed = 1; + break; + } + } +} + +static void +setup_routing_socket(struct socksetup *data) +{ + int sock = socket(PF_ROUTE, SOCK_RAW, 0); + if (sock < 0) { + int e = errno; + krb5_klog_syslog(LOG_INFO, "couldn't set up routing socket: %s", + strerror(e)); + } else { + krb5_klog_syslog(LOG_INFO, "routing socket is fd %d", sock); + add_fd(data, sock, CONN_ROUTING, process_routing_update); + setnbio(sock); + FD_SET(sock, &sstate.rfds); + } +} +#endif + +/* XXX */ +extern int krb5int_debug_sendto_kdc; +extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t); + +krb5_error_code +setup_network() +{ + 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; irealm_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.retval = 0; + krb5_klog_syslog (LOG_INFO, "setting up network..."); +#ifdef HAVE_STRUCT_RT_MSGHDR + setup_routing_socket(&setup_data); +#endif + /* 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. */ + setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6; + setup_udp_pktinfo_ports(&setup_data); + if (setup_data.udp_flags) { + 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) { + kdc_err(NULL, 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 int +recv_from_to(int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen, + struct sockaddr *to, socklen_t *tolen) +{ +#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) + if (to && tolen) { + /* Clobber with something recognizeable in case we try to use + the address. */ + memset(to, 0x40, *tolen); + *tolen = 0; + } + return recvfrom(s, buf, len, flags, from, fromlen); +#else + int r; + struct iovec iov; + char cmsg[CMSG_SPACE(sizeof(union pktinfo))]; + struct cmsghdr *cmsgptr; + struct msghdr msg; + + if (!to || !tolen) + return recvfrom(s, buf, len, flags, from, fromlen); + + /* Clobber with something recognizeable in case we can't extract + the address but try to use it anyways. */ + memset(to, 0x40, *tolen); + + iov.iov_base = buf; + iov.iov_len = len; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = from; + msg.msg_namelen = *fromlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof(cmsg); + + r = recvmsg(s, &msg, flags); + if (r < 0) + return r; + *fromlen = msg.msg_namelen; + + /* On Darwin (and presumably all *BSD with KAME stacks), + CMSG_FIRSTHDR doesn't check for a non-zero controllen. RFC + 3542 recommends making this check, even though the (new) spec + for CMSG_FIRSTHDR says it's supposed to do the check. */ + if (msg.msg_controllen) { + cmsgptr = CMSG_FIRSTHDR(&msg); + while (cmsgptr) { +#ifdef IP_PKTINFO + if (cmsgptr->cmsg_level == IPPROTO_IP + && cmsgptr->cmsg_type == IP_PKTINFO + && *tolen >= sizeof(struct sockaddr_in)) { + struct in_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in)); + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; + ((struct sockaddr_in *)to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return r; + } +#endif +#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)&& defined(HAVE_STRUCT_IN6_PKTINFO) + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO + && *tolen >= sizeof(struct sockaddr_in6)) { + struct in6_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in6)); + pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr; + ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6; + *tolen = sizeof(struct sockaddr_in6); + return r; + } +#endif + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr); + } + } + /* No info about destination addr was available. */ + *tolen = 0; + return r; +#endif +} + +static int +send_to_from(int s, void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen, + const struct sockaddr *from, socklen_t fromlen) +{ +#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) + return sendto(s, buf, len, flags, to, tolen); +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsgptr; + char cbuf[CMSG_SPACE(sizeof(union pktinfo))]; + + if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) { + use_sendto: + return sendto(s, buf, len, flags, to, tolen); + } + + iov.iov_base = buf; + iov.iov_len = len; + /* Truncation? */ + if (iov.iov_len != len) + return EINVAL; + memset(cbuf, 0, sizeof(cbuf)); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *) to; + msg.msg_namelen = tolen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cbuf; + /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL + on Linux. */ + msg.msg_controllen = sizeof(cbuf); + cmsgptr = CMSG_FIRSTHDR(&msg); + msg.msg_controllen = 0; + + switch (from->sa_family) { +#if defined(IP_PKTINFO) + case AF_INET: + if (fromlen != sizeof(struct sockaddr_in)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + { + struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in *from4 = (const struct sockaddr_in *)from; + p->ipi_spec_dst = from4->sin_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + break; +#endif +#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) + case AF_INET6: + if (fromlen != sizeof(struct sockaddr_in6)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + { + struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from; + p->ipi6_addr = from6->sin6_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + break; +#endif + default: + goto use_sendto; + } + return sendmsg(s, &msg, flags); +#endif +} + +static krb5_error_code +make_too_big_error (krb5_data **out) +{ + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + + *out = NULL; + memset(&errpkt, 0, sizeof(errpkt)); + + retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec); + if (retval) + return retval; + errpkt.error = KRB_ERR_RESPONSE_TOO_BIG; + errpkt.server = tgs_server; + errpkt.client = NULL; + 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_packet(struct connection *conn, int selflags) +{ + int cc; + socklen_t saddr_len, daddr_len; + krb5_fulladdr faddr; + krb5_error_code retval; + struct sockaddr_storage saddr, daddr; + 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); + daddr_len = sizeof(daddr); + cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0, + (struct sockaddr *)&saddr, &saddr_len, + (struct sockaddr *)&daddr, &daddr_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 + ) + kdc_err(NULL, errno, "while receiving from network"); + return; + } + if (!cc) + return; /* zero-length packet? */ + +#if 0 + if (daddr_len > 0) { + char addrbuf[100]; + if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf), + 0, 0, NI_NUMERICHOST)) + strlcpy(addrbuf, "?", sizeof(addrbuf)); + kdc_err(NULL, 0, "pktinfo says local addr is %s", addrbuf); + } +#endif + + 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))) { + kdc_err(NULL, retval, "while dispatching (udp)"); + return; + } + if (response == NULL) + return; + if (response->length > max_dgram_reply_size) { + krb5_free_data(kdc_context, response); + retval = make_too_big_error(&response); + if (retval) { + krb5_klog_syslog(LOG_ERR, + "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s", + error_message(retval)); + return; + } + } + cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0, + (struct sockaddr *)&saddr, saddr_len, + (struct sockaddr *)&daddr, daddr_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) { + strlcpy(addrbuf, "?", sizeof(addrbuf)); + } + kdc_err(NULL, errno, "while sending reply to %s/%d", + addrbuf, faddr.port); + return; + } + if (cc != response->length) { + kdc_err(NULL, 0, "short reply write %d vs %d\n", + response->length, cc); + } + 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, 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; + set_cloexec_fd(s); +#ifndef _WIN32 + if (s >= FD_SETSIZE) { + close(s); + return; + } +#endif + setnbio(s), setnolinger(s), setkeepalive(s); + + sockdata.retval = 0; + + newconn = add_tcp_data_fd(&sockdata, s); + if (newconn == NULL) + return; + + if (getnameinfo((struct sockaddr *)&addr_s, addrlen, + newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(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++ = '.'; + strlcpy(p, tmpbuf, end - p); + } + } +#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) { + kdc_err(NULL, 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 +queue_tcp_outgoing_response(struct connection *conn) +{ + store_32_be(conn->u.tcp.response->length, conn->u.tcp.lenbuf); + 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_SET(conn->fd, &sstate.wfds); +} + +static void +process_tcp_connection(struct connection *conn, 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 = load_32_be(p); + 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) { + kdc_err(NULL, err, "while dispatching (tcp)"); + goto kill_tcp_connection; + } + have_response: + queue_tcp_outgoing_response(conn); + FD_CLR(conn->fd, &sstate.rfds); + } + } else + abort(); + + return; + +kill_tcp_connection: + kill_tcp_connection(conn); +} + +static void service_conn(struct connection *conn, int selflags) +{ + conn->service(conn, selflags); +} + +/* from sendto_kdc.c */ +static int getcurtime(struct timeval *tvp) +{ +#ifdef _WIN32 + struct _timeb tb; + _ftime(&tb); + tvp->tv_sec = tb.time; + tvp->tv_usec = tb.millitm * 1000; + return 0; +#else + return gettimeofday(tvp, 0) ? errno : 0; +#endif +} + +krb5_error_code +listen_and_process() +{ + 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, netchanged = 0; + krb5_error_code err; + + if (conns == (struct connection **) NULL) + return KDC5_NONET; + + while (!signal_requests_exit) { + if (signal_requests_hup) { + int k; + + krb5_klog_reopen(kdc_context); + for (k = 0; k < kdc_numrealms; k++) + krb5_db_invoke(kdc_realmlist[k]->realm_context, + KRB5_KDB_METHOD_REFRESH_POLICY, + NULL, NULL); + signal_requests_hup = 0; + } + + if (network_reconfiguration_needed) { + krb5_klog_syslog(LOG_INFO, "network reconfiguration needed"); + /* It might be tidier to add a timer-callback interface to + the control loop here, but for this one use, it's not a + big deal. */ + err = getcurtime(&sstate.end_time); + if (err) { + kdc_err(NULL, err, "while getting the time"); + continue; + } + sstate.end_time.tv_sec += 3; + netchanged = 1; + } else + sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0; + + err = krb5int_cm_call_select(&sstate, &sout, &sret); + if (err) { + if (err != EINTR) + kdc_err(NULL, err, "while selecting for network input(1)"); + continue; + } + if (sret == 0 && netchanged) { + network_reconfiguration_needed = 0; + closedown_network(); + err = setup_network(); + if (err) { + kdc_err(NULL, err, "while reinitializing network"); + return err; + } + netchanged = 0; + } + if (sret == -1) { + if (errno != EINTR) + kdc_err(NULL, errno, "while selecting for network input(2)"); + continue; + } + nfound = sret; + for (i=0; i 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], sflags); + } + } + krb5_klog_syslog(LOG_INFO, "shutdown signal received"); + return 0; +} + +krb5_error_code +closedown_network() +{ + int i; + struct connection *conn; + + if (conns == (struct connection **) NULL) + return KDC5_NONET; + + FOREACH_ELT (connections, i, conn) { + if (conn->fd >= 0) { + krb5_klog_syslog(LOG_INFO, "closing down fd %d", conn->fd); + (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-7/src/kdc/pkinit_apple_server.c b/krb5-1-7/src/kdc/pkinit_apple_server.c new file mode 100644 index 000000000..b86c63444 --- /dev/null +++ b/krb5-1-7/src/kdc/pkinit_apple_server.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_server.c - Server side routines for PKINIT, Mac OS X version + * + * Created 21 May 2004 by Doug Mitchell at Apple. + */ + +#if APPLE_PKINIT + +#include "pkinit_server.h" +#include "pkinit_asn1.h" +#include "pkinit_cms.h" +#include + +#define PKINIT_DEBUG 0 +#if PKINIT_DEBUG +#define pkiDebug(args...) printf(args) +#else +#define pkiDebug(args...) +#endif + +/* + * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain. + * Optionally returns various components. + */ +krb5_error_code krb5int_pkinit_as_req_parse( + krb5_context context, + const krb5_data *as_req, + krb5_timestamp *kctime, /* optionally RETURNED */ + krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ + krb5_ui_4 *nonce, /* optionally RETURNED */ + krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ + krb5int_cert_sig_status *cert_status,/* optionally RETURNED */ + krb5_ui_4 *num_cms_types, /* optionally RETURNED */ + krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ + + /* + * Cert fields, all optionally RETURNED. + * + * signer_cert is the full X.509 leaf cert from the incoming SignedData. + * all_certs is an array of all of the certs in the incoming SignedData, + * in full X.509 form. + */ + krb5_data *signer_cert, /* content mallocd */ + krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ + krb5_data **all_certs, /* krb5_data's and their content mallocd */ + + /* + * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded + * issuer/serial numbers. + */ + krb5_ui_4 *num_trusted_CAs, /* sizeof *trusted_CAs */ + krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ + + /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ + krb5_data *kdc_cert) +{ + krb5_error_code krtn; + krb5_data signed_auth_pack = {0, 0, NULL}; + krb5_data raw_auth_pack = {0, 0, NULL}; + krb5_data *raw_auth_pack_p = NULL; + krb5_boolean proceed = FALSE; + krb5_boolean need_auth_pack = FALSE; + krb5int_cms_content_type content_type; + krb5_pkinit_cert_db_t cert_db = NULL; + krb5_boolean is_signed; + krb5_boolean is_encrypted; + + assert(as_req != NULL); + + /* + * We always have to decode the top-level AS-REQ... + */ + krtn = krb5int_pkinit_pa_pk_as_req_decode(as_req, &signed_auth_pack, + num_trusted_CAs, trusted_CAs, /* optional */ + kdc_cert); /* optional */ + if (krtn) { + pkiDebug("krb5int_pkinit_pa_pk_as_req_decode returned %d\n", (int)krtn); + return krtn; + } + + /* Do we need info about or from the ContentInto or AuthPack? */ + if ((kctime != NULL) || (cusec != NULL) || (nonce != NULL) || + (pa_cksum != NULL) || (cms_types != NULL)) { + need_auth_pack = TRUE; + raw_auth_pack_p = &raw_auth_pack; + } + if (need_auth_pack || (cert_status != NULL) || + (signer_cert != NULL) || (all_certs != NULL)) { + proceed = TRUE; + } + if (!proceed) { + krtn = 0; + goto err_out; + } + + /* Parse and possibly verify the ContentInfo */ + krtn = krb5_pkinit_get_kdc_cert_db(&cert_db); + if (krtn) { + pkiDebug("pa_pk_as_req_parse: error in krb5_pkinit_get_kdc_cert_db\n"); + goto err_out; + } + krtn = krb5int_pkinit_parse_cms_msg(&signed_auth_pack, cert_db, TRUE, + &is_signed, &is_encrypted, + raw_auth_pack_p, &content_type, signer_cert, cert_status, + num_all_certs, all_certs); + if (krtn) { + pkiDebug("krb5int_pkinit_parse_content_info returned %d\n", (int)krtn); + goto err_out; + } + + if (is_encrypted || !is_signed) { + pkiDebug("pkinit_parse_content_info: is_encrypted %s is_signed %s!\n", + is_encrypted ? "true" :"false", + is_signed ? "true" : "false"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto err_out; + } + if (content_type != ECT_PkAuthData) { + pkiDebug("authPack eContentType %d!\n", (int)content_type); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto err_out; + } + + /* optionally parse contents of authPack */ + if (need_auth_pack) { + krtn = krb5int_pkinit_auth_pack_decode(&raw_auth_pack, kctime, + cusec, nonce, pa_cksum, + cms_types, num_cms_types); + if(krtn) { + pkiDebug("krb5int_pkinit_auth_pack_decode returned %d\n", (int)krtn); + goto err_out; + } + } + +err_out: + /* free temp mallocd data that we didn't pass back to caller */ + if(signed_auth_pack.data) { + free(signed_auth_pack.data); + } + if(raw_auth_pack.data) { + free(raw_auth_pack.data); + } + if(cert_db) { + krb5_pkinit_release_cert_db(cert_db); + } + return krtn; +} + +/* + * Create a PA-PK-AS-REP message, public key (no Diffie Hellman) version. + * + * PA-PK-AS-REP is based on ReplyKeyPack like so: + * + * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) + */ +krb5_error_code krb5int_pkinit_as_rep_create( + krb5_context context, + const krb5_keyblock *key_block, + const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ + krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ + krb5_boolean include_server_cert,/* include signer_cert in SignerInfo */ + const krb5_data *recipient_cert, /* client's cert */ + + /* + * These correspond to the same out-parameters from + * krb5int_pkinit_as_req_parse(). All are optional. + */ + krb5_ui_4 num_cms_types, + const krb5int_algorithm_id *cms_types, + krb5_ui_4 num_trusted_CAs, + krb5_data *trusted_CAs, + krb5_data *kdc_cert, + + krb5_data *as_rep) /* mallocd and RETURNED */ +{ + krb5_data reply_key_pack = {0, 0, NULL}; + krb5_error_code krtn; + krb5_data enc_key_pack = {0, 0, NULL}; + + /* innermost content = ReplyKeyPack */ + krtn = krb5int_pkinit_reply_key_pack_encode(key_block, checksum, + &reply_key_pack); + if (krtn) { + return krtn; + } + + /* + * Put that in an EnvelopedData(SignedData) + * -- SignedData.EncapsulatedData.ContentType = id-pkinit-rkeyData + */ + krtn = krb5int_pkinit_create_cms_msg(&reply_key_pack, + signer_cert, + recipient_cert, + ECT_PkReplyKeyKata, + num_cms_types, cms_types, + &enc_key_pack); + if (krtn) { + goto err_out; + } + + /* + * Finally, wrap that inside of PA-PK-AS-REP + */ + krtn = krb5int_pkinit_pa_pk_as_rep_encode(NULL, &enc_key_pack, as_rep); + +err_out: + if (reply_key_pack.data) { + free(reply_key_pack.data); + } + if (enc_key_pack.data) { + free(enc_key_pack.data); + } + return krtn; +} + +#endif /* APPLE_PKINIT */ diff --git a/krb5-1-7/src/kdc/pkinit_server.h b/krb5-1-7/src/kdc/pkinit_server.h new file mode 100644 index 000000000..773b497e0 --- /dev/null +++ b/krb5-1-7/src/kdc/pkinit_server.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_server.h - Server side routines for PKINIT + * + * Created 21 May 2004 by Doug Mitchell at Apple. + */ + +#ifndef _PKINIT_SERVER_H_ +#define _PKINIT_SERVER_H_ + +#include "krb5.h" +#include "pkinit_cms.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain + * if cert_status is non-NULL. Optionally returns various components. + */ +krb5_error_code krb5int_pkinit_as_req_parse( + krb5_context context, + const krb5_data *as_req, + krb5_timestamp *kctime, /* optionally RETURNED */ + krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ + krb5_ui_4 *nonce, /* optionally RETURNED */ + krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ + krb5int_cert_sig_status *cert_status, /* optionally RETURNED */ + krb5_ui_4 *num_cms_types, /* optionally RETURNED */ + krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ + + /* + * Cert fields, all optionally RETURNED. + * + * signer_cert is the full X.509 leaf cert from the incoming SignedData. + * all_certs is an array of all of the certs in the incoming SignedData, + * in full X.509 form. + */ + krb5_data *signer_cert, /* content mallocd */ + krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ + krb5_data **all_certs, /* krb5_data's and their content mallocd */ + + /* + * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded + * issuer/serial numbers. + */ + krb5_ui_4 *num_trusted_CAs, /* sizeof *trustedCAs */ + krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ + + /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ + krb5_data *kdc_cert); + + +/* + * Create a PA-PK-AS-REP message, public key (no Diffie Hellman) version. + * + * PA-PK-AS-REP is based on ReplyKeyPack like so: + * + * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) + */ +krb5_error_code krb5int_pkinit_as_rep_create( + krb5_context context, + const krb5_keyblock *key_block, + const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ + krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ + krb5_boolean include_server_cert, /* include signer_cert in SignerInfo */ + const krb5_data *recipient_cert, /* client's cert */ + + /* + * These correspond to the same out-parameters from + * krb5int_pkinit_as_req_parse(). All are optional. + */ + krb5_ui_4 num_cms_types, + const krb5int_algorithm_id *cms_types, + krb5_ui_4 num_trusted_CAs, + krb5_data *trusted_CAs, + krb5_data *kdc_cert, + + /* result here, mallocd and RETURNED */ + krb5_data *as_rep); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKINIT_SERVER_H_ */ diff --git a/krb5-1-7/src/kdc/policy.c b/krb5-1-7/src/kdc/policy.c new file mode 100644 index 000000000..58b26f73d --- /dev/null +++ b/krb5-1-7/src/kdc/policy.c @@ -0,0 +1,166 @@ +/* + * 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. + */ +/* + * Copyright (c) 2006-2008, 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" +#include "kdc_util.h" +#include "extern.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) +{ + krb5_error_code code; + kdb_check_policy_as_req req; + kdb_check_policy_as_rep rep; + krb5_data req_data; + krb5_data rep_data; + +#if 0 + /* An AS request must include the addresses field */ + if (request->addresses == 0) { + *status = "NO ADDRESS"; + return KRB5KDC_ERR_POLICY; + } +#endif + + memset(&req, 0, sizeof(req)); + memset(&rep, 0, sizeof(rep)); + + req.request = request; + req.client = &client; + req.server = &server; + req.kdc_time = kdc_time; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = (void *)&rep; + rep_data.length = sizeof(rep); + + code = krb5_db_invoke(kdc_context, + KRB5_KDB_METHOD_CHECK_POLICY_AS, + &req_data, + &rep_data); + if (code == KRB5_KDB_DBTYPE_NOSUP) + return 0; + + *status = rep.status; + + if (code != 0) { + code -= ERROR_TABLE_BASE_krb5; + if (code < 0 || code > 128) + code = KRB_ERR_GENERIC; + } + + return code; +} + +/* + * 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) +{ + krb5_error_code code; + kdb_check_policy_tgs_req req; + kdb_check_policy_tgs_rep rep; + krb5_data req_data; + krb5_data rep_data; + +#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 + + memset(&req, 0, sizeof(req)); + memset(&rep, 0, sizeof(rep)); + + req.request = request; + req.server = &server; + req.ticket = ticket; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = (void *)&rep; + rep_data.length = sizeof(rep); + + code = krb5_db_invoke(kdc_context, + KRB5_KDB_METHOD_CHECK_POLICY_TGS, + &req_data, + &rep_data); + if (code == KRB5_KDB_DBTYPE_NOSUP) + return 0; + + *status = rep.status; + + if (code != 0) { + code -= ERROR_TABLE_BASE_krb5; + if (code < 0 || code > 128) + code = KRB_ERR_GENERIC; + } + + return code; +} + diff --git a/krb5-1-7/src/kdc/policy.h b/krb5-1-7/src/kdc/policy.h new file mode 100644 index 000000000..fe8307625 --- /dev/null +++ b/krb5-1-7/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-7/src/kdc/replay.c b/krb5-1-7/src/kdc/replay.c new file mode 100644 index 000000000..e6c48a4ea --- /dev/null +++ b/krb5-1-7/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-7/src/kdc/rtest.c b/krb5-1-7/src/kdc/rtest.c new file mode 100644 index 000000000..87f4a9652 --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/kdc/rtest.good b/krb5-1-7/src/kdc/rtest.good new file mode 100644 index 000000000..4eecf6e30 --- /dev/null +++ b/krb5-1-7/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-7/src/kdc/rtscript b/krb5-1-7/src/kdc/rtscript new file mode 100755 index 000000000..8803e3325 --- /dev/null +++ b/krb5-1-7/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-7/src/kim/agent/mac/AuthenticationController.h b/krb5-1-7/src/kim/agent/mac/AuthenticationController.h new file mode 100644 index 000000000..ba0b21223 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/AuthenticationController.h @@ -0,0 +1,120 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +@class IPCClient; +@class KerberosTimeFormatter; +@class BadgedImageView; + +@interface AuthenticationController : NSWindowController { + IPCClient *associatedClient; + + IBOutlet KerberosTimeFormatter *lifetimeFormatter; + + IBOutlet NSView *containerView; + IBOutlet NSView *identityView; + IBOutlet NSView *passwordView; + IBOutlet NSView *samView; + IBOutlet NSView *changePasswordView; + IBOutlet NSView *expiredPasswordView; + IBOutlet NSView *errorView; + + IBOutlet BadgedImageView *enterBadge; + IBOutlet BadgedImageView *passwordBadge; + IBOutlet BadgedImageView *samBadge; + IBOutlet BadgedImageView *changePasswordBadge; + IBOutlet BadgedImageView *errorBadge; + + IBOutlet NSProgressIndicator *enterSpinny; + IBOutlet NSProgressIndicator *passwordSpinny; + IBOutlet NSProgressIndicator *samSpinny; + IBOutlet NSProgressIndicator *changePasswordSpinny; + + // Controls that need to be made key + IBOutlet NSTextField *identityField; + IBOutlet NSTextField *passwordField; + IBOutlet NSTextField *samPromptField; + IBOutlet NSTextField *oldPasswordField; + + // Other controls of interest + IBOutlet NSButton *rememberPasswordInKeychainCheckBox; + + IBOutlet NSObjectController *glueController; + + IBOutlet NSWindow *ticketOptionsSheet; + IBOutlet NSObjectController *ticketOptionsController; + BOOL visibleAsSheet; + + IBOutlet NSSlider *validLifetimeSlider; + IBOutlet NSSlider *renewableLifetimeSlider; + + NSMutableArray *favoriteIdentities; + NSMutableDictionary *favoriteOptions; +} + +@property (readwrite, retain) IPCClient *associatedClient; +@property (readwrite, retain) NSMutableArray *favoriteIdentities; +@property (readwrite, retain) NSMutableDictionary *favoriteOptions; + +- (void) setContent: (NSMutableDictionary *) newContent; + +- (void) showEnterIdentity: (NSWindow *) parentWindow; +- (void) showAuthPrompt: (NSWindow *) parentWindow; +- (void) showEnterPassword: (NSWindow *) parentWindow; +- (void) showSAM: (NSWindow *) parentWindow; +- (void) showChangePassword: (NSWindow *) parentWindow; +- (void) showError: (NSWindow *) parentWindow; + +- (IBAction) cancel: (id) sender; +- (IBAction) enterIdentity: (id) sender; +- (IBAction) answerAuthPrompt: (id) sender; +- (IBAction) changePassword: (id) sender; +- (IBAction) showedError: (id) sender; + +- (IBAction) checkboxDidChange: (id) sender; +- (IBAction) sliderDidChange: (id) sender; + +- (IBAction) showTicketOptions: (id) sender; +- (IBAction) cancelTicketOptions: (id) sender; +- (IBAction) saveTicketOptions: (id) sender; + +- (IBAction) cancelAuthSheet: (id) sender; + +- (void) authSheetDidEnd: (NSWindow *) sheet + returnCode: (int) returnCode + contextInfo: (void *) contextInfo; +- (void) ticketOptionsSheetDidEnd: (NSWindow *) sheet + returnCode: (int) returnCode + contextInfo: (void *) contextInfo; + +- (IBAction) changePasswordGearAction: (id) sender; + +- (void) swapView: (NSView *) aView; +- (void) showSpinny; +- (void) hideSpinny; +- (void) clearSensitiveInputs; +- (void) clearAllInputs; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/AuthenticationController.m b/krb5-1-7/src/kim/agent/mac/AuthenticationController.m new file mode 100644 index 000000000..5a9c8b6f1 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/AuthenticationController.m @@ -0,0 +1,678 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "AuthenticationController.h" +#import "IPCClient.h" +#import "KerberosFormatters.h" +#import "BadgedImageView.h" + +// to get kim_prompt_type enum +#import + +/* + * glueController KVC mapping is as follows: + * name = client app name + * path = client app bundle path + * title = suggested label for prompt field + * message = desired large text message + * description = longer, detailed, small text message + * username = 'user' part of 'user@REALM.ORG' + * realm = 'REALM.ORG' part of 'user@REALM.ORG' + * realm_history = past realms the user has entered + * prompt_response = auth prompt response + * allow_save_password = whether or not to show the 'save password in keychain' checkbox + * should_save_password = whether or not to save the password in the keychain + * old_password = for change password dialog + * new_password = " + * verify_password = " + */ + +// localization keys and tables + +#define ACLocalizationTable @"AuthenticationController" + +#define ACAppPrincReqKey @"AuthControllerApplicationPrincipalRequest" +#define ACPrincReqKey @"AuthControllerPrincipalRequest" +#define ACAppPasswordReqKey @"AuthControllerApplicationPasswordRequest" +#define ACPasswordReqKey @"AuthControllerPasswordRequest" +#define ACPasswordChangeExpired @"ChangePasswordPasswordExpired" +#define ACPasswordChangeApp @"ChangePasswordApplicationRequest" +#define ACPasswordChangePrinc @"ChangePasswordPrincipalRequest" + +@implementation AuthenticationController + +@synthesize associatedClient; +@synthesize favoriteIdentities; +@synthesize favoriteOptions; + +- (id) init +{ + return [self initWithWindowNibName: @"Authentication"]; +} + +- (void) awakeFromNib +{ + [[self window] center]; + // We need to float over the loginwindow and SecurityAgent so use its hardcoded level. + [[self window] setLevel:NSModalPanelWindowLevel]; + + visibleAsSheet = NO; + + lifetimeFormatter.displaySeconds = NO; + lifetimeFormatter.displayShortFormat = NO; + + [glueController addObserver:self + forKeyPath:identity_string_keypath + options:NSKeyValueObservingOptionNew + context:ACKVOContext]; + [glueController addObserver:self + forKeyPath:prompt_response_keypath + options:NSKeyValueObservingOptionNew + context:ACKVOContext]; + [glueController addObserver:self + forKeyPath:old_password_keypath + options:NSKeyValueObservingOptionNew + context:ACKVOContext]; + [glueController addObserver:self + forKeyPath:new_password_keypath + options:NSKeyValueObservingOptionNew + context:ACKVOContext]; + [glueController addObserver:self + forKeyPath:verify_password_keypath + options:NSKeyValueObservingOptionNew + context:ACKVOContext]; + +} + +- (void) dealloc +{ + [glueController removeObserver:self forKeyPath:identity_string_keypath]; + [glueController removeObserver:self forKeyPath:prompt_response_keypath]; + [super dealloc]; +} + +- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + BOOL valid = NO; + + if ([(NSString *) context isEqualToString:ACKVOContext]) { + if ([keyPath isEqualToString:identity_string_keypath]) { + valid = [KIMUtilities validateIdentity:[glueController valueForKeyPath:identity_string_keypath]]; + [glueController setValue:[NSNumber numberWithBool:valid] + forKeyPath:enable_identity_ok_keypath]; + } + else if ([keyPath isEqualToString:prompt_response_keypath]) { + valid = ([[glueController valueForKeyPath:prompt_response_keypath] length] > 0); + [glueController setValue:[NSNumber numberWithBool:valid] + forKeyPath:enable_prompt_ok_keypath]; + } + else if ([keyPath isEqualToString:old_password_keypath] || + [keyPath isEqualToString:new_password_keypath] || + [keyPath isEqualToString:verify_password_keypath]) { + NSString *oldString = [glueController valueForKeyPath:old_password_keypath]; + NSString *newString = [glueController valueForKeyPath:new_password_keypath]; + NSString *verifyString = [glueController valueForKeyPath:verify_password_keypath]; + valid = ([oldString length] > 0 && [newString length] > 0 && + [verifyString length] > 0 && [newString isEqualToString:verifyString]); + [glueController setValue:[NSNumber numberWithBool:valid] + forKeyPath:change_password_ok_keypath]; + } + else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } + } + else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +- (IBAction) showWindow: (id) sender +{ + + [super showWindow:sender]; +} + +- (void) showWithParent: (NSWindow *) parentWindow +{ + // attach as sheet if given a parentWindow + if (parentWindow && !visibleAsSheet) { + [NSApp beginSheet:[self window] + modalForWindow:parentWindow + modalDelegate:self + didEndSelector:@selector(authSheetDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; + } + // else, display as normal + else { + [self showWindow:nil]; + } +} + +- (void) windowWillBeginSheet: (NSNotification *) notification +{ + visibleAsSheet = YES; +} + +- (void) windowDidEndSheet: (NSNotification *) notification +{ + visibleAsSheet = NO; +} + +- (void) setContent: (NSMutableDictionary *) newContent +{ + [self window]; // wake up the nib connections + [glueController setContent:newContent]; +} + +- (void) swapView: (NSView *) aView +{ + NSWindow *theWindow = [self window]; + NSRect windowFrame; + NSRect viewFrame; + + [[containerView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + windowFrame = [theWindow frame]; + viewFrame = [theWindow frameRectForContentRect:[aView frame]]; + windowFrame.origin.y -= viewFrame.size.height - windowFrame.size.height; + + windowFrame.size.width = viewFrame.size.width; + windowFrame.size.height = viewFrame.size.height; + + [theWindow setFrame:windowFrame display:YES animate:YES]; + + [containerView addSubview:aView]; + +} + +- (void) showSpinny +{ + [enterSpinny startAnimation: nil]; + [passwordSpinny startAnimation: nil]; + [samSpinny startAnimation: nil]; + [changePasswordSpinny startAnimation: nil]; + [glueController setValue:[NSNumber numberWithBool:NO] + forKeyPath:accepting_input_keypath]; +} + +- (void) hideSpinny +{ + [enterSpinny stopAnimation: nil]; + [passwordSpinny stopAnimation: nil]; + [samSpinny stopAnimation: nil]; + [changePasswordSpinny stopAnimation: nil]; + [glueController setValue:[NSNumber numberWithBool:YES] + forKeyPath:accepting_input_keypath]; +} + +- (void) clearSensitiveInputs +{ + [glueController setValue:@"" + forKeyPath:prompt_response_keypath]; +} + +- (void) clearAllInputs +{ + [glueController setValue:@"" + forKeyPath:old_password_keypath]; + [glueController setValue:@"" + forKeyPath:new_password_keypath]; + [glueController setValue:@"" + forKeyPath:verify_password_keypath]; + [self clearSensitiveInputs]; +} + +- (void) showEnterIdentity: (NSWindow *) parentWindow +{ + kim_error err = KIM_NO_ERROR; + NSWindow *theWindow = [self window]; + NSString *key = (associatedClient.name) ? ACAppPrincReqKey : ACPrincReqKey; + NSString *message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + associatedClient.name]; + + self.favoriteIdentities = [NSMutableArray array]; + self.favoriteOptions = [NSMutableDictionary dictionary]; + // get array of favorite identity strings and associated options + + if (!err) { + kim_preferences preferences = NULL; + kim_options kimOptions = NULL; + kim_count i; + kim_count count = 0; + + err = kim_preferences_create(&preferences); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities(preferences, + &count); + } + + for (i = 0; !err && i < count; i++) { + kim_identity kimIdentity = NULL; + kim_string display_string = NULL; + NSString *identityString = nil; + + err = kim_preferences_get_favorite_identity_at_index(preferences, + i, + &kimIdentity, + &kimOptions); + if (!err) { + err = kim_identity_get_display_string(kimIdentity, &display_string); + } + if (!err && display_string) { + identityString = [NSString stringWithUTF8String:display_string]; + [favoriteIdentities addObject:identityString]; + } + if (!err) { + [favoriteOptions setObject:[KIMUtilities dictionaryForKimOptions:kimOptions] + forKey:identityString]; + } + + kim_options_free(&kimOptions); + kim_string_free (&display_string); + kim_identity_free (&kimIdentity); + } + + kim_preferences_free(&preferences); + } + + [glueController setValue:favoriteIdentities forKeyPath:favorite_strings_keypath]; + + // wake up the nib connections and adjust window size + [self window]; + // set up controls with info from associatedClient + [enterBadge setBadgePath:associatedClient.path]; + [glueController setValue:message + forKeyPath:message_keypath]; + + [self hideSpinny]; + [self clearAllInputs]; + + [self swapView:identityView]; + + [theWindow makeFirstResponder:identityField]; + + [self showWithParent: parentWindow]; +} + +- (void) showAuthPrompt: (NSWindow *) parentWindow +{ + uint32_t type = [[glueController valueForKeyPath:@"content.prompt_type"] unsignedIntegerValue]; + + [self hideSpinny]; + + [self clearSensitiveInputs]; + + switch (type) { + case kim_prompt_type_password : + [self showEnterPassword: parentWindow]; break; + case kim_prompt_type_preauth : + default : + [self showSAM: parentWindow]; break; + } +} + +- (void) showEnterPassword: (NSWindow *) parentWindow +{ + CGFloat shrinkBy; + NSRect frame; + NSString *key = nil; + NSString *message = nil; + NSWindow *theWindow = [self window]; + + if ([associatedClient.name isEqualToString:[[NSBundle mainBundle] bundlePath]]) { + key = ACPasswordReqKey; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + [glueController valueForKeyPath:identity_string_keypath]]; + } else { + key = ACAppPasswordReqKey; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + associatedClient.name, + [glueController valueForKeyPath:identity_string_keypath]]; + } + [glueController setValue:message + forKeyPath:message_keypath]; + + // set badge + [passwordBadge setBadgePath:associatedClient.path]; + + // adjust for checkbox visibility + if (![[glueController valueForKeyPath:allow_save_password_keypath] boolValue] && + ![rememberPasswordInKeychainCheckBox isHidden]) { + [rememberPasswordInKeychainCheckBox setHidden:YES]; + frame = [passwordView frame]; + shrinkBy = ([passwordField frame].origin.y - + [rememberPasswordInKeychainCheckBox frame].origin.y); + frame.size.height -= shrinkBy; + [passwordView setFrame:frame]; + } + + [self swapView:passwordView]; + + [theWindow makeFirstResponder:passwordField]; + [self showWithParent:parentWindow]; +} + +- (void) showSAM: (NSWindow *) parentWindow +{ + // set badge + [samBadge setBadgePath:associatedClient.path]; + + [glueController setValue:[NSNumber numberWithBool:NO] + forKeyPath:allow_save_password_keypath]; + + [self swapView:samView]; + + [[self window] makeFirstResponder:samPromptField]; + [self showWithParent:parentWindow]; +} + +- (void) showChangePassword: (NSWindow *) parentWindow +{ + NSString *key = ([glueController valueForKeyPath:password_expired_keypath]) ? ACAppPrincReqKey : ACPrincReqKey; + NSString *message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + associatedClient.name]; + NSWindow *theWindow = [self window]; + + + BOOL expired = [[glueController valueForKeyPath:password_expired_keypath] boolValue]; + BOOL calledBySelf = [associatedClient.path isEqualToString:[[NSBundle mainBundle] bundlePath]]; + + if (calledBySelf) { + key = ACPasswordChangePrinc; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + [glueController valueForKeyPath:identity_string_keypath]]; + // Please change the Kerberos password for \"%@\" + } else if (!expired) { + key = ACPasswordChangeApp; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + associatedClient.name, + [glueController valueForKeyPath:identity_string_keypath]]; + // %@ requires that you change the Kerberos password for \"%@\" + } else { + key = ACPasswordChangeExpired; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, ACLocalizationTable, NULL), + [glueController valueForKeyPath:identity_string_keypath]]; + // Your password has expired, would you like to change it? + } + [glueController setValue:message forKeyPath:message_keypath]; + + // set badge + [changePasswordBadge setBadgePath:associatedClient.path]; + + [self hideSpinny]; + + if (![[self window] isVisible]) { + [self clearAllInputs]; + } + + [self swapView:changePasswordView]; + + [self showWithParent:parentWindow]; + + [theWindow makeFirstResponder:oldPasswordField]; +} + +- (void) showError: (NSWindow *) parentWindow +{ + // wake up the nib connections and adjust window size + [self window]; + // set badge + [errorBadge setBadgePath:associatedClient.path]; + + [self hideSpinny]; + [self swapView:errorView]; + + [self showWithParent:parentWindow]; +} + +- (IBAction) checkboxDidChange: (id) sender +{ + if ([[ticketOptionsController valueForKeyPath:uses_default_options_keypath] boolValue]) { + // merge defaults onto current options + NSMutableDictionary *currentOptions = [ticketOptionsController content]; + NSDictionary *defaultOptions = [KIMUtilities dictionaryForKimOptions:NULL]; + [currentOptions addEntriesFromDictionary:defaultOptions]; + // update the sliders, since their values aren't bound + [validLifetimeSlider setDoubleValue:[[ticketOptionsController valueForKeyPath:valid_lifetime_keypath] doubleValue]]; + [renewableLifetimeSlider setDoubleValue:[[ticketOptionsController valueForKeyPath:renewal_lifetime_keypath] doubleValue]]; + } +} + +- (IBAction) sliderDidChange: (id) sender +{ + NSInteger increment = 0; + NSInteger newValue = 0; + NSString *keyPath = nil; + if ([sender isEqual:validLifetimeSlider]) { + increment = VALID_LIFETIME_INCREMENT; + keyPath = valid_lifetime_keypath; + } + else if ([sender isEqual:renewableLifetimeSlider]) { + increment = RENEWABLE_LIFETIME_INCREMENT; + keyPath = renewal_lifetime_keypath; + } + if (increment > 0) { + newValue = ([sender integerValue] / increment) * increment; + [ticketOptionsController setValue:[NSNumber numberWithInteger:newValue] + forKeyPath:keyPath]; + } +} + +- (IBAction) showTicketOptions: (id) sender +{ + NSDictionary *options = nil; + NSString *expandedString = nil; + // if this is a favorite, try to load its default options + [identityField validateEditing]; + + expandedString = [KIMUtilities expandedIdentity:[identityField stringValue]]; + + // edit the favorite options for this favorite identity + if (expandedString) { + options = [favoriteOptions objectForKey:expandedString]; + } + + // else, it's not a favorite identity. use default options + if (!options) { + options = [KIMUtilities dictionaryForKimOptions:KIM_OPTIONS_DEFAULT]; + } + + [ticketOptionsController setContent:[[options mutableCopy] autorelease]]; + + [ticketOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities minValidLifetime]] + forKeyPath:min_valid_keypath]; + [ticketOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities maxValidLifetime]] + forKeyPath:max_valid_keypath]; + [ticketOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities minRenewableLifetime]] + forKeyPath:min_renewable_keypath]; + [ticketOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities maxRenewableLifetime]] + forKeyPath:max_renewable_keypath]; + + [validLifetimeSlider setIntegerValue: + [[ticketOptionsController valueForKeyPath:valid_lifetime_keypath] integerValue]]; + [renewableLifetimeSlider setIntegerValue: + [[ticketOptionsController valueForKeyPath:renewal_lifetime_keypath] integerValue]]; + [self sliderDidChange:validLifetimeSlider]; + [self sliderDidChange:renewableLifetimeSlider]; + + [NSApp beginSheet:ticketOptionsSheet + modalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(ticketOptionsSheetDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; +} + +- (IBAction) cancelTicketOptions: (id) sender +{ + [NSApp endSheet:ticketOptionsSheet returnCode:NSUserCancelledError]; +} + +- (IBAction) saveTicketOptions: (id) sender +{ + [NSApp endSheet:ticketOptionsSheet]; +} + +- (IBAction) cancelAuthSheet: (id) sender +{ + [NSApp endSheet:[self window]]; +} + +- (void) authSheetDidEnd: (NSWindow *) sheet + returnCode: (int) returnCode + contextInfo: (void *) contextInfo +{ + [sheet orderOut:nil]; +} + + +- (void) ticketOptionsSheetDidEnd: (NSWindow *) sheet + returnCode: (int) returnCode + contextInfo: (void *) contextInfo +{ + if (returnCode == NSUserCancelledError) { + // discard new options + [ticketOptionsController setContent:nil]; + } else { + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_identity identity = NULL; + kim_options options = NULL; + NSString *expandedString = [KIMUtilities expandedIdentity:[identityField stringValue]];; + + // replace options if favorite exists + // add to favorites if not already in list + if (!expandedString) { + err = KIM_BAD_PRINCIPAL_STRING_ERR; + } + if (!err) { + [favoriteOptions setObject:[ticketOptionsController content] + forKey:expandedString]; + } + if (!err) { + err = kim_preferences_create(&prefs); + } + if (!err) { + err = kim_identity_create_from_string(&identity, [[identityField stringValue] UTF8String]); + } + if (!err) { + options = [KIMUtilities kimOptionsForDictionary:[ticketOptionsController content]]; + } + + if (!identity) { err = KIM_BAD_PRINCIPAL_STRING_ERR; } + + if (!err) { + err = kim_preferences_remove_favorite_identity(prefs, identity); + } + if (!err) { + err = kim_preferences_add_favorite_identity(prefs, identity, options); + } + if (!err) { + err = kim_preferences_synchronize(prefs); + } + + kim_preferences_free(&prefs); + kim_options_free(&options); + kim_identity_free(&identity); + } + [ticketOptionsSheet orderOut:nil]; +} + +- (IBAction) changePasswordGearAction: (id) sender +{ + NSString *expandedString = [KIMUtilities expandedIdentity:[identityField stringValue]]; + NSDictionary *options = [favoriteOptions objectForKey:expandedString]; + + if (!options) { + options = [glueController valueForKeyPath:options_keypath]; + } + + [self showSpinny]; + + // the principal must already be valid to get this far + [associatedClient didEnterIdentity:expandedString options:options wantsChangePassword:YES]; +} + +- (IBAction) cancel: (id) sender +{ + [NSApp endSheet:[self window]]; + [associatedClient didCancel]; +} + +- (IBAction) enterIdentity: (id) sender +{ + NSString *expandedString = [KIMUtilities expandedIdentity:[identityField stringValue]]; + NSDictionary *options = [favoriteOptions objectForKey:expandedString]; + + if (!options) { + options = [glueController valueForKeyPath:options_keypath]; + } + + [self showSpinny]; + + // the principal must already be valid to get this far + [associatedClient didEnterIdentity:expandedString options:options wantsChangePassword:NO]; +} + +- (IBAction) answerAuthPrompt: (id) sender +{ + NSString *responseString = [glueController valueForKeyPath:prompt_response_keypath]; + NSNumber *saveResponse = [glueController valueForKeyPath:should_save_password_keypath]; + + if (!saveResponse) { + saveResponse = [NSNumber numberWithBool:NO]; + } + + [self showSpinny]; + [associatedClient didPromptForAuth:responseString + saveResponse:saveResponse]; +} + +- (IBAction) changePassword: (id) sender +{ + NSString *oldString = [glueController valueForKeyPath:old_password_keypath]; + NSString *newString = [glueController valueForKeyPath:new_password_keypath]; + NSString *verifyString = [glueController valueForKeyPath:verify_password_keypath]; + + [self showSpinny]; + + [associatedClient didChangePassword:oldString + newPassword:newString + verifyPassword:verifyString]; + [NSApp endSheet:[self window]]; +} + +- (IBAction) showedError: (id) sender +{ + [associatedClient didHandleError]; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/BadgedImageView.h b/krb5-1-7/src/kim/agent/mac/BadgedImageView.h new file mode 100644 index 000000000..4fba86727 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/BadgedImageView.h @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + + +@interface BadgedImageView : NSView { + NSImage *iconImage; + NSImage *badgeImage; +} + +- (id) initWithFrame: (NSRect) frameRect; +- (void) dealloc; +- (void) setBadgeImage: (NSImage *) image; +- (void) setBadgePath: (NSString *) path; +- (void) drawRect: (NSRect) rect; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/BadgedImageView.m b/krb5-1-7/src/kim/agent/mac/BadgedImageView.m new file mode 100644 index 000000000..167130aca --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/BadgedImageView.m @@ -0,0 +1,104 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "BadgedImageView.h" + + +@implementation BadgedImageView + +// --------------------------------------------------------------------------- + +- (id) initWithFrame: (NSRect) frameRect +{ + if ((self = [super initWithFrame: frameRect])) { + iconImage = NULL; + badgeImage = NULL; + } + return self; +} + +// --------------------------------------------------------------------------- + +- (void) dealloc +{ + if (iconImage ) { [iconImage release]; } + if (badgeImage) { [badgeImage release]; } + + [super dealloc]; +} + +// --------------------------------------------------------------------------- + +- (void) setBadgeImage: (NSImage *) image +{ + if (badgeImage) { [badgeImage release]; } + + badgeImage = [image retain]; + [self setNeedsDisplay: YES]; +} + +// --------------------------------------------------------------------------- + +- (void) setBadgePath: (NSString *) path +{ + NSImage *newImage = [[NSWorkspace sharedWorkspace] iconForFile: path]; + [self setBadgeImage: newImage]; +} + +// --------------------------------------------------------------------------- + +- (void) drawRect: (NSRect) rect +{ + float frameSize = [self frame].size.width; + float iconSize = 64.0; + float badgeSize = 32.0; + + if (!iconImage) { + iconImage = [[NSImage imageNamed: @"NSApplicationIcon"] retain]; + } + + if (iconImage) { + [self lockFocus]; + + // Clear an old badged icon + [[NSColor windowBackgroundColor] set]; + NSRectFill ([self frame]); + + [iconImage setScalesWhenResized: YES]; + [iconImage setSize: NSMakeSize (iconSize, iconSize)]; + [iconImage compositeToPoint: NSMakePoint (0.0, frameSize - iconSize) + operation: NSCompositeSourceOver]; + + if (badgeImage) { + // draw badge + [badgeImage setScalesWhenResized: YES]; + [badgeImage setSize: NSMakeSize (badgeSize, badgeSize)]; + [badgeImage compositeToPoint: NSMakePoint (frameSize - badgeSize, 0.0) + operation: NSCompositeSourceOver]; + } + [self unlockFocus]; + } +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/IPCClient.h b/krb5-1-7/src/kim/agent/mac/IPCClient.h new file mode 100644 index 000000000..0bea6000b --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/IPCClient.h @@ -0,0 +1,74 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#import "KIMUtilities.h" + +@class SelectIdentityController; +@class AuthenticationController; +@class Identities; + +@interface IPCClient : NSObject { + mach_port_t port; + NSString *name; + NSString *path; + NSInteger state; + NSMutableDictionary *currentInfo; + + SelectIdentityController *selectController; + AuthenticationController *authController; +} + +@property (assign) mach_port_t port; +@property (readwrite, retain) NSString *name; +@property (readwrite, retain) NSString *path; +@property (assign) NSInteger state; +@property (readwrite, retain) NSMutableDictionary *currentInfo; +@property (readonly, retain) SelectIdentityController *selectController; +@property (readonly, retain) AuthenticationController *authController; + +- (void) cleanup; +- (void) saveIdentityToFavoritesIfSuccessful; + +- (kim_error) selectIdentity: (NSDictionary *) info; +- (kim_error) enterIdentity: (NSDictionary *) info; +- (kim_error) promptForAuth: (NSDictionary *) info; +- (kim_error) changePassword: (NSDictionary *) info; +- (kim_error) handleError: (NSDictionary *) info; + +- (void) didCancel; +- (void) didSelectIdentity: (NSString *) identityString + options: (NSDictionary *) options + wantsChangePassword: (BOOL) wantsChangePassword; +- (void) didEnterIdentity: (NSString *) identityString + options: (NSDictionary *) options + wantsChangePassword: (BOOL) wantsChangePassword; +- (void) didPromptForAuth: (NSString *) responseString saveResponse: (NSNumber *) saveResponse; +- (void) didChangePassword: (NSString *) oldPassword + newPassword: (NSString *) newPassword + verifyPassword: (NSString *) verifyPassword; +- (void) didHandleError; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/IPCClient.m b/krb5-1-7/src/kim/agent/mac/IPCClient.m new file mode 100644 index 000000000..d4ac8a699 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/IPCClient.m @@ -0,0 +1,338 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "IPCClient.h" +#import "SelectIdentityController.h" +#import "AuthenticationController.h" +#import "KerberosAgentListener.h" +#import "Identities.h" + +enum krb_agent_client_state { + ipc_client_state_idle, + ipc_client_state_init, + ipc_client_state_enter, + ipc_client_state_select, + ipc_client_state_auth_prompt, + ipc_client_state_change_password, + ipc_client_state_handle_error, + ipc_client_state_fini, +}; + +@interface IPCClient () + +@property (readwrite, retain) SelectIdentityController *selectController; +@property (readwrite, retain) AuthenticationController *authController; + +@end + + +@implementation IPCClient + +@synthesize port; +@synthesize name; +@synthesize path; +@synthesize state; +@synthesize currentInfo; +@synthesize selectController; +@synthesize authController; + +- (BOOL) isEqual: (IPCClient *) otherClient +{ + return (self.port == otherClient.port); +} + +- (NSUInteger) hash +{ + return self.port; +} + +- (id) init +{ + self = [super init]; + if (self != nil) { + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_identity identity = NULL; + kim_string identity_string = NULL; + + self.state = ipc_client_state_init; + self.selectController = [[[SelectIdentityController alloc] init] autorelease]; + self.authController = [[[AuthenticationController alloc] init] autorelease]; + self.selectController.associatedClient = self; + self.authController.associatedClient = self; + self.currentInfo = [NSMutableDictionary dictionary]; + + // pre-populate the identity_string if there's a default identity + err = kim_preferences_create(&prefs); + if (!err && prefs) { + err = kim_preferences_get_client_identity(prefs, &identity); + } + if (!err && identity) { + err = kim_identity_get_display_string(identity, &identity_string); + } + if (!err && identity_string) { + [self.currentInfo setObject:[NSString stringWithUTF8String:identity_string] + forKey:@"identity_string"]; + } + + kim_string_free(&identity_string); + kim_identity_free(&identity); + kim_preferences_free(&prefs); + } + return self; +} + +- (void) cleanup +{ + if (![[self.selectController window] isVisible]) { + [self saveIdentityToFavoritesIfSuccessful]; + } + [self.selectController close]; + [self.authController close]; + self.selectController = nil; + self.authController = nil; + self.currentInfo = nil; +} + +- (void) saveIdentityToFavoritesIfSuccessful +{ + NSString *identityString = [self.currentInfo valueForKeyPath:@"identity_string"]; + NSDictionary *options = [self.currentInfo valueForKeyPath:@"options"]; + + Identities *identities = [[Identities alloc] init]; + Identity *theIdentity = [[Identity alloc] initWithIdentity:identityString + options:options]; + for (Identity *anIdentity in [identities identities]) { + if ([anIdentity isEqual:theIdentity]) { + if (!anIdentity.favorite) { + anIdentity.favorite = YES; + [identities synchronizePreferences]; + } + break; + } + } +} + +- (void) didCancel +{ + kim_error err = KIM_USER_CANCELED_ERR; + if (self.state == ipc_client_state_select) { + [KerberosAgentListener didSelectIdentity:self.currentInfo error:err]; + } + else if (self.state == ipc_client_state_enter) { + [KerberosAgentListener didEnterIdentity:self.currentInfo error:err]; + } + else if (self.state == ipc_client_state_select) { + [KerberosAgentListener didSelectIdentity:self.currentInfo error:err]; + } + else if (self.state == ipc_client_state_auth_prompt) { + [KerberosAgentListener didPromptForAuth:self.currentInfo error:err]; + } + else if (self.state == ipc_client_state_change_password) { + [KerberosAgentListener didChangePassword:self.currentInfo error:err]; + } + + if ([[self.selectController window] isVisible]) { + self.state = ipc_client_state_select; + } + else { + self.state = ipc_client_state_idle; + } +} + +- (kim_error) selectIdentity: (NSDictionary *) info +{ + [self.currentInfo addEntriesFromDictionary:info]; + self.state = ipc_client_state_select; + + if ([[self.authController window] isVisible]) { + [self.authController cancelAuthSheet:nil]; + } + + [self.selectController setContent:self.currentInfo]; + [self.selectController showWindow:nil]; + + return 0; +} + +- (void) didSelectIdentity: (NSString *) identityString + options: (NSDictionary *) options + wantsChangePassword: (BOOL) wantsChangePassword +{ + [self.currentInfo setObject:identityString forKey:@"identity_string"]; + // if the user set custom options, use those + if (options) { + [self.currentInfo setObject:options forKey:@"options"]; + } + // else use the options in the hints + else { + [self.currentInfo setObject:[self.currentInfo valueForKeyPath:@"hints.options"] + forKey:@"options"]; + } + [self.currentInfo setObject:[NSNumber numberWithBool:wantsChangePassword] forKey:@"wants_change_password"]; + + [KerberosAgentListener didSelectIdentity:self.currentInfo error:0]; + + // clean up state + if (!wantsChangePassword) { + self.state = ipc_client_state_idle; + } +} + +- (kim_error) enterIdentity: (NSDictionary *) info +{ + NSWindow *parentWindow = nil; + + [self.currentInfo addEntriesFromDictionary:info]; + + if ([[self.selectController window] isVisible]) { + parentWindow = [selectController window]; + } + + self.state = ipc_client_state_enter; + + [self.authController setContent:self.currentInfo]; + [self.authController showEnterIdentity:parentWindow]; + + return 0; +} + +- (void) didEnterIdentity: (NSString *) identityString + options: (NSDictionary *) options + wantsChangePassword: (BOOL) wantsChangePassword +{ + [self.currentInfo setObject:identityString forKey:@"identity_string"]; + [self.currentInfo setObject:options forKey:@"options"]; + [self.currentInfo setObject:[NSNumber numberWithBool:wantsChangePassword] forKey:@"wants_change_password"]; + [KerberosAgentListener didEnterIdentity:self.currentInfo error:0]; + + if ([[self.selectController window] isVisible]) { + self.state = ipc_client_state_select; + } + else { + self.state = ipc_client_state_idle; + } +} + +- (kim_error) promptForAuth: (NSDictionary *) info +{ + NSWindow *parentWindow = nil; + + [self.currentInfo addEntriesFromDictionary:info]; + + if ([[self.selectController window] isVisible]) { + parentWindow = [selectController window]; + } + + self.state = ipc_client_state_auth_prompt; + + [self.authController setContent:self.currentInfo]; + [self.authController showAuthPrompt:parentWindow]; + + return 0; +} + +- (void) didPromptForAuth: (NSString *) responseString saveResponse: (NSNumber *) saveResponse +{ + [self.currentInfo setObject:responseString forKey:@"prompt_response"]; + [self.currentInfo setObject:saveResponse forKey:@"save_response"]; + [KerberosAgentListener didPromptForAuth:self.currentInfo error:0]; + + if ([[self.selectController window] isVisible]) { + self.state = ipc_client_state_select; + } + else { + self.state = ipc_client_state_idle; + } +} + +- (kim_error) changePassword: (NSDictionary *) info +{ + NSWindow *parentWindow = nil; + + [self.currentInfo addEntriesFromDictionary:info]; + + if ([[self.selectController window] isVisible]) { + parentWindow = [selectController window]; + } + + self.state = ipc_client_state_change_password; + + [self.authController setContent:self.currentInfo]; + [self.authController showChangePassword:parentWindow]; + + return 0; +} + +- (void) didChangePassword: (NSString *) oldPassword + newPassword: (NSString *) newPassword + verifyPassword: (NSString *) verifyPassword +{ + [self.currentInfo setObject:oldPassword forKey:@"old_password"]; + [self.currentInfo setObject:newPassword forKey:@"new_password"]; + [self.currentInfo setObject:verifyPassword forKey:@"verify_password"]; + + if ([[self.selectController window] isVisible]) { + self.state = ipc_client_state_select; + } + else { + self.state = ipc_client_state_idle; + } + + [KerberosAgentListener didChangePassword:self.currentInfo error:0]; +} + + +- (kim_error) handleError: (NSDictionary *) info +{ + NSWindow *parentWindow = nil; + + [self.currentInfo addEntriesFromDictionary:info]; + + if ([[self.selectController window] isVisible]) { + parentWindow = [selectController window]; + } + + self.state = ipc_client_state_handle_error; + + [self.authController setContent:self.currentInfo]; + [self.authController showError:parentWindow]; + + return 0; +} + +- (void) didHandleError +{ + if ([[self.selectController window] isVisible]) { + self.state = ipc_client_state_select; + } + else { + self.state = ipc_client_state_idle; + } + + [KerberosAgentListener didHandleError:self.currentInfo error:0]; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/Identities.h b/krb5-1-7/src/kim/agent/mac/Identities.h new file mode 100644 index 000000000..712abb31c --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/Identities.h @@ -0,0 +1,89 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#import +#import "KIMUtilities.h" + +@interface Identity : NSObject { + NSString *identity; + NSDictionary *options; + kim_credential_state state; + NSDate *expirationDate; + BOOL favorite; +} + +@property (readwrite, retain) NSString *identity; +@property (readwrite, retain) NSDictionary *options; +@property (assign) kim_credential_state state; +@property (assign) BOOL favorite; +@property (readwrite, retain) NSDate *expirationDate; + +// derived properties +@property (readonly) kim_identity kimIdentity; +@property (readonly) kim_options kimOptions; +@property (readonly) NSString *expirationString; +@property (readonly) NSString *validLifetimeString; +@property (readonly) NSString *renewableLifetimeString; +@property (readonly) BOOL hasCCache; +@property (readwrite) BOOL isRenewable; +@property (readwrite) BOOL isForwardable; +@property (readwrite) BOOL isAddressless; +@property (readwrite) BOOL isProxiable; +@property (readwrite) NSUInteger validLifetime; +@property (readwrite) NSUInteger renewableLifetime; + +- (id) initWithKimIdentity: (kim_identity) an_identity kimOptions: (kim_options) some_options; +- (id) initWithFavoriteIdentity: (kim_identity) an_identity options: (kim_options) some_options; +- (id) initWithIdentity: (NSString *) anIdentity options: (NSDictionary *) someOptions; + +- (BOOL) isEqualToKIMIdentity: (kim_identity) identity; +- (BOOL) isEqual: (Identity *)otherIdentity; + +- (void) resetOptions; +- (void) toggleFavorite; +- (BOOL) addToFavorites; +- (BOOL) removeFromFavorites; + +@end + + +@interface Identities : NSObject { + NSMutableArray *favoriteIdentities; + NSMutableArray *identities; + NSConnection *threadConnection; +} + +@property(readonly, retain) NSMutableArray *identities; +@property(readonly) NSUInteger minimumValidLifetime; +@property(readonly) NSUInteger maximumValidLifetime; +@property(readonly) NSUInteger minimumRenewableLifetime; +@property(readonly) NSUInteger maximumRenewableLifetime; + +- (void) reload; +- (int) update; +- (kim_error) addIdentity: (Identity *) anIdentity; +- (void) synchronizePreferences; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/Identities.m b/krb5-1-7/src/kim/agent/mac/Identities.m new file mode 100644 index 000000000..1fa7e6ef4 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/Identities.m @@ -0,0 +1,849 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "Identities.h" +#import + +@interface Identity () + +- (NSString *)stringForLifetime:(NSUInteger)lifetime; + +@end + + +@implementation Identity + +@synthesize identity; +@synthesize options; +@synthesize expirationDate; +@synthesize state; +@synthesize favorite; + +#pragma mark Initialization & Comparison + +// --------------------------------------------------------------------------- + ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key +{ + NSMutableSet *result = [[super keyPathsForValuesAffectingValueForKey:key] mutableCopy]; + NSSet *otherKeys = nil; + + [result unionSet:otherKeys]; + + return [result autorelease]; +} + +// --------------------------------------------------------------------------- + +- (id) init +{ + return [self initWithIdentity: @"" options: [NSDictionary dictionary]]; +} + +// --------------------------------------------------------------------------- + +- (id) initWithKimIdentity: (kim_identity) an_identity kimOptions: (kim_options) some_options +{ + kim_error err = KIM_NO_ERROR; + kim_string identity_string = NULL; + + if (!err) { + err = kim_identity_get_display_string(an_identity, &identity_string); + } + return [self initWithIdentity:[NSString stringWithUTF8String:identity_string] + options:[KIMUtilities dictionaryForKimOptions:some_options]]; +} + +// --------------------------------------------------------------------------- + +- (id) initWithFavoriteIdentity: (kim_identity) an_identity options: (kim_options) some_options +{ + if ((self = [self initWithKimIdentity: an_identity kimOptions: some_options])) { + self.favorite = TRUE; + } + + return self; +} + +// --------------------------------------------------------------------------- + +- (id) initWithIdentity: (NSString *) anIdentity options: (NSDictionary *) someOptions +{ + self = [super init]; + if (self != nil) { + self.identity = anIdentity; + self.options = someOptions; + self.state = kim_credentials_state_not_yet_valid; + self.expirationDate = [NSDate dateWithTimeIntervalSince1970:0]; + self.favorite = NO; + } + return self; +} + +// --------------------------------------------------------------------------- + +- (BOOL) isEqualToKIMIdentity: (kim_identity) comparison_identity +{ + kim_error err = KIM_NO_ERROR; + kim_comparison comparison; + kim_identity an_identity = self.kimIdentity; + + err = kim_identity_compare (an_identity, comparison_identity, &comparison); + + kim_identity_free(&an_identity); + + return (!err && kim_comparison_is_equal_to (comparison)); +} + +// --------------------------------------------------------------------------- + +- (BOOL) isEqual: (Identity *)otherIdentity +{ + return ([self isEqualToKIMIdentity:otherIdentity.kimIdentity]); +} + +// --------------------------------------------------------------------------- + +- (NSUInteger)hash +{ + return [self.identity hash]; +} + +// --------------------------------------------------------------------------- + +- (NSComparisonResult) compare: (Identity *)otherIdentity +{ + return ([self.identity compare:otherIdentity.identity]); +} + +#pragma mark Actions + +// --------------------------------------------------------------------------- + +- (void) resetOptions +{ + // property setter converts NULL into actual kim_options with default settings + kim_error err = KIM_NO_ERROR; + kim_options some_options = NULL; + + err = kim_options_create(&some_options); + + if (!err) { + self.options = [KIMUtilities dictionaryForKimOptions:some_options]; + } + + log_kim_error_to_console(err); + + kim_options_free(&some_options); +} + +// --------------------------------------------------------------------------- + +- (void) toggleFavorite +{ + if (self.favorite) { + [self removeFromFavorites]; + } else { + [self addToFavorites]; + } +} + +// --------------------------------------------------------------------------- + +- (BOOL) addToFavorites +{ + kim_error err = KIM_NO_ERROR; + kim_preferences preferences = NULL; + kim_identity an_identity = self.kimIdentity; + kim_options some_options = self.kimOptions; + + err = kim_preferences_create(&preferences); + + if (!err) { + err = kim_preferences_add_favorite_identity(preferences, an_identity, some_options); + } + if (!err) { + err = kim_preferences_synchronize(preferences); + } + + if (!err) { + self.favorite = true; + } else { + log_kim_error_to_console(err); + } + + kim_preferences_free(&preferences); + kim_identity_free(&an_identity); + kim_options_free(&some_options); + + return (err != KIM_NO_ERROR); +} + +// --------------------------------------------------------------------------- + +- (BOOL) removeFromFavorites +{ + kim_error err = KIM_NO_ERROR; + kim_preferences preferences = NULL; + kim_identity an_identity = self.kimIdentity; + + err = kim_preferences_create(&preferences); + + if (!err) { + err = kim_preferences_remove_favorite_identity(preferences, an_identity); + } + if (!err) { + err = kim_preferences_synchronize(preferences); + } + if (!err) { + self.favorite = false; + } else { + log_kim_error_to_console(err); + } + + kim_preferences_free(&preferences); + kim_identity_free(&an_identity); + + return (err != KIM_NO_ERROR); +} + +#pragma mark Accessors + +// --------------------------------------------------------------------------- + +- (BOOL) hasCCache +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + err = kim_ccache_create_from_client_identity(&ccache, self.kimIdentity); + + if (!err && ccache) { + return TRUE; + } + + return FALSE; +} + + +// --------------------------------------------------------------------------- + +- (kim_identity) kimIdentity +{ + kim_error err = KIM_NO_ERROR; + kim_identity an_identity = NULL; + err = kim_identity_create_from_string(&an_identity, [self.identity UTF8String]); + return an_identity; +} + +// --------------------------------------------------------------------------- + +- (kim_options) kimOptions +{ + return [KIMUtilities kimOptionsForDictionary:self.options]; +} + +// --------------------------------------------------------------------------- + +- (BOOL) isRenewable +{ + return [[self.options valueForKey:@"renewable"] boolValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setIsRenewable: (BOOL) value +{ + [self.options setValue:[NSNumber numberWithBool:value] + forKey:@"renewable"]; +} + +// --------------------------------------------------------------------------- + +- (BOOL) isForwardable +{ + return [[self.options valueForKey:@"forwardable"] boolValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setIsForwardable: (BOOL) value +{ + [self.options setValue:[NSNumber numberWithBool:value] + forKey:@"forwardable"]; +} + +// --------------------------------------------------------------------------- + +- (BOOL) isAddressless +{ + return [[self.options valueForKey:@"addressless"] boolValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setIsAddressless: (BOOL) value +{ + [self.options setValue:[NSNumber numberWithBool:value] + forKey:@"addressless"]; +} + +// --------------------------------------------------------------------------- + +- (BOOL) isProxiable +{ + return [[self.options valueForKey:@"proxiable"] boolValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setIsProxiable: (BOOL) value +{ + [self.options setValue:[NSNumber numberWithBool:value] + forKey:@"proxiable"]; +} + +// --------------------------------------------------------------------------- + +- (NSUInteger) validLifetime +{ + return [[self.options valueForKey:@"valid_lifetime"] unsignedIntegerValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setValidLifetime: (NSUInteger) newLifetime +{ + [self.options setValue:[NSNumber numberWithUnsignedInteger:newLifetime] + forKey:@"valid_lifetime"]; +} + +// --------------------------------------------------------------------------- + +- (NSUInteger) renewableLifetime +{ + return [[self.options valueForKey:@"renewable_lifetime"] unsignedIntegerValue]; +} + +// --------------------------------------------------------------------------- + +- (void) setRenewableLifetime: (NSUInteger) newLifetime +{ + [self.options setValue:[NSNumber numberWithUnsignedInteger:newLifetime] + forKey:@"renewable_lifetime"]; +} + +#pragma mark String representations + +// --------------------------------------------------------------------------- + +- (NSString *) expirationString +{ + NSString *result = nil; + NSTimeInterval lifetime = [self.expirationDate timeIntervalSinceNow]; + if (lifetime > 0) { + NSTimeInterval seconds = fmod(lifetime, 60); + NSTimeInterval minutes = fmod(lifetime, 60 % 60); + NSTimeInterval hours = fmod(lifetime, 3600 % 24); + NSTimeInterval days = fmod(lifetime, 86400); + + if (seconds > 0) { seconds = 0; minutes++; } + if (minutes > 59) { minutes = 0; hours++; } + if (hours > 23) { hours = 0; days++; } + + result = [NSString stringWithFormat:@"%02ld:%02ld", hours, minutes]; + } else { + result = @"--:--"; + } + + return result; +} + +// --------------------------------------------------------------------------- + +- (NSString *) validLifetimeString +{ + return [self stringForLifetime:self.validLifetime]; +} + +// --------------------------------------------------------------------------- + +- (NSString *) renewableLifetimeString +{ + return [self stringForLifetime:self.renewableLifetime]; +} + +// --------------------------------------------------------------------------- + +- (NSString *)stringForLifetime:(NSUInteger)lifetime +{ + NSMutableArray *parts = nil; + NSUInteger days, hours, minutes, seconds; + + days = (lifetime / 86400); + hours = (lifetime / (60 * 60) % 24); + minutes = (lifetime / 60 % 60); + seconds = (lifetime % 60); + + if (seconds > 0) { seconds = 0; minutes++; } + if (minutes > 59) { minutes = 0; hours++; } + if (hours > 23) { hours = 0; days++; } + + parts = [NSMutableArray arrayWithCapacity:3]; + if (days > 0) { + [parts addObject:[NSString stringWithFormat:@"%d days", days]]; + } + if (hours > 0) { + [parts addObject:[NSString stringWithFormat:@"%d hours", hours]]; + } + if (minutes > 0) { + [parts addObject:[NSString stringWithFormat:@"%d minutes", minutes]]; + } + if ([parts count] == 0) { + [parts addObject:@"0"]; + } + return [parts componentsJoinedByString:@", "]; +} + +// --------------------------------------------------------------------------- + +- (NSString *) description +{ + return [NSString stringWithFormat:@"%@ (%@) %@", self.identity, self.expirationString, [super description]]; +} + +@end + +@interface Identities () + +@property(readwrite, retain) NSMutableArray *favoriteIdentities; +@property(readwrite, retain) NSMutableArray *identities; + +@end + +@implementation Identities + +@synthesize favoriteIdentities; +@synthesize identities; + +// --------------------------------------------------------------------------- + ++ (void) waitForChange: (NSArray *) portArray +{ + NSAutoreleasePool *pool; + NSConnection *connection; + + pool = [[NSAutoreleasePool alloc] init]; + + connection = [NSConnection connectionWithReceivePort: [portArray objectAtIndex: 0] + sendPort: [portArray objectAtIndex: 1]]; + + { + cc_int32 err = ccNoError; + cc_context_t context = NULL; + + err = cc_initialize (&context, ccapi_version_max, NULL, NULL); + + while (!err) { + // This call puts the thread to sleep + err = cc_context_wait_for_change (context); + + if (!err) { + // NSLog (@"%s thread noticed update", __FUNCTION__); + } else { + // NSLog (@"%s thread got error %d (%s)", __FUNCTION__, err, [KIMUtilities stringForLastKIMError:err]); + err = 0; /* The server quit unexpectedly -- just try again */ + } + + //NSLog(@"waited %@", [[NSThread currentThread] description]); + [(Identities *) [connection rootProxy] reload]; + sleep (1); + } + + if (context) { cc_context_release (context); } + } + +// NSLog (@"%s thread exiting", __FUNCTION__); + [pool release]; +} + +// --------------------------------------------------------------------------- + +- (id) init +{ + if ((self = [super init])) { + int err = 0; + + threadConnection = NULL; + + [self reload]; + + if (!err) { + NSPort *port1 = [NSPort port]; + NSPort *port2 = [NSPort port]; + if (!port1 || !port2) { err = ENOMEM; } + + if (!err) { + threadConnection = [[NSConnection alloc] initWithReceivePort: port1 + sendPort: port2]; + if (!threadConnection) { err = ENOMEM; } + } + + if (!err) { + [threadConnection setRootObject: self]; + + [NSThread detachNewThreadSelector: @selector(waitForChange:) + toTarget: [self class] + withObject: [NSArray arrayWithObjects: port2, port1, NULL]]; + } + } + + if (err) { + [self release]; + return NULL; + } + } + + return self; +} + +// --------------------------------------------------------------------------- + +- (void) dealloc +{ + if (identities ) { [identities release]; } + if (favoriteIdentities) { [favoriteIdentities release]; } + if (threadConnection ) { [threadConnection release]; } + + [super dealloc]; +} + +// --------------------------------------------------------------------------- + +- (void) reload +{ + kim_error err = KIM_NO_ERROR; + + NSMutableArray *newFavoriteIdentities = NULL; + + favoriteIdentities = NULL; + + if (!err) { + newFavoriteIdentities = [[NSMutableArray alloc] init]; + if (!newFavoriteIdentities) { err = ENOMEM; } + } + + if (!err) { + kim_preferences preferences = NULL; + kim_options kimOptions = NULL; + kim_count i; + kim_count count = 0; + + err = kim_preferences_create(&preferences); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities(preferences, + &count); + } + + for (i = 0; !err && i < count; i++) { + kim_identity kimIdentity = NULL; + Identity *identity = NULL; + + err = kim_preferences_get_favorite_identity_at_index(preferences, + i, + &kimIdentity, + &kimOptions); + + if (!err) { + identity = [[Identity alloc] initWithFavoriteIdentity: kimIdentity options: kimOptions]; + if (!identity) { err = ENOMEM; } + } + + if (!err) { + [newFavoriteIdentities addObject: identity]; + } + + if (identity) { + [identity release]; + identity = nil; + } + + kim_options_free(&kimOptions); + kim_identity_free (&kimIdentity); + } + + kim_preferences_free(&preferences); + } + + + if (!err) { + self.favoriteIdentities = newFavoriteIdentities; + if (!favoriteIdentities) { err = ENOMEM; } + } + + + if (newFavoriteIdentities) { + [newFavoriteIdentities release]; + newFavoriteIdentities = nil; + } + + if (!err) { + [identities release]; + identities = nil; + err = [self update]; + } +} + +// --------------------------------------------------------------------------- + +- (int) update +{ + kim_error err = KIM_NO_ERROR; + NSMutableSet *newIdentities = NULL; + kim_ccache_iterator iterator = NULL; + + if (!err) { + newIdentities = [NSMutableSet set]; + if (!newIdentities) { err = ENOMEM; } + } + + if (!err) { + err = kim_ccache_iterator_create (&iterator); + } + + // Build list of identities with existing ccaches + //NSLog(@"updating %@", [[NSThread currentThread] description]); + while (!err) { + kim_ccache ccache = NULL; + kim_identity an_identity = NULL; + kim_options some_options = NULL; + kim_credential_state state = kim_credentials_state_valid; + kim_time expiration_time = 0; + + err = kim_ccache_iterator_next (iterator, &ccache); + if (!err && !ccache) { break; } + + if (!err) { + err = kim_ccache_get_client_identity (ccache, &an_identity); + } + + if (!err) { + err = kim_ccache_get_state (ccache, &state); + } + + if (!err && state == kim_credentials_state_valid) { + err = kim_ccache_get_expiration_time (ccache, &expiration_time); + } + + if (!err) { + err = kim_ccache_get_options(ccache, &some_options); + } + + if (!err) { + Identity *identity = [[Identity alloc] initWithKimIdentity:an_identity kimOptions:some_options]; + if (!identity) { err = ENOMEM; } + + if (!err) { + identity.state = state; + identity.expirationDate = [NSDate dateWithTimeIntervalSince1970:expiration_time]; + [newIdentities addObject: identity]; + } + + [identity release]; + identity = nil; + } + + if (err == KIM_NO_CREDENTIALS_ERR) { + /* ccache is empty, just ignore it */ + err = KIM_NO_ERROR; + } + + if (err) { + log_kim_error_to_console(err); + } + + kim_options_free (&some_options); + kim_identity_free (&an_identity); + kim_ccache_free (&ccache); + } + + kim_ccache_iterator_free (&iterator); + + + // Copy ccache state to favorites + for (Identity *identity in self.favoriteIdentities) { + Identity *matchingIdentity = [newIdentities member:identity]; + if (matchingIdentity) { + identity.state = matchingIdentity.state; + identity.expirationDate = matchingIdentity.expirationDate; + [newIdentities removeObject:matchingIdentity]; + } else { + identity.state = kim_credentials_state_expired; + identity.expirationDate = [NSDate distantPast]; + } + } + + + // Add unused favorites + [newIdentities unionSet:[NSSet setWithArray:self.favoriteIdentities]]; + + if (!err) { +// [self.identities removeAllObjects]; +// [self.identities addObjectsFromArray:[newIdentities allObjects]]; +// [self.identities sortUsingSelector:@selector(compare:)]; + + self.identities = [[[[newIdentities allObjects] sortedArrayUsingSelector:@selector(compare:)] mutableCopy] autorelease]; + + + if (!identities) { err = ENOMEM; } + } else { + log_kim_error_to_console(err); + } + + return err; +} + +// --------------------------------------------------------------------------- + +- (kim_error) addIdentity: (Identity *) anIdentity +{ + kim_error err = KIM_NO_ERROR; + + if (![self.identities containsObject:anIdentity]) { + NSMutableArray *newArray = [[self.identities mutableCopy] autorelease]; + [newArray addObject:anIdentity]; + self.identities = newArray; + } else { + err = KIM_IDENTITY_ALREADY_IN_LIST_ERR; + } + + return err; +} + +// --------------------------------------------------------------------------- + +- (void) synchronizePreferences +{ + // Saves the kim_options for all identities in the list to disk, then rebuilds the Identities array from scratch + + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + + err = kim_preferences_create(&prefs); + + if (!err) { + err = kim_preferences_remove_all_favorite_identities(prefs); + } + + for (Identity *identity in self.identities) { + if (!err && identity.favorite == TRUE) { + err = kim_preferences_add_favorite_identity(prefs, identity.kimIdentity, identity.kimOptions); + } + } + + if (!err) { + err = kim_preferences_synchronize(prefs); + } + + kim_preferences_free(&prefs); + + if (err) { + log_kim_error_to_console(err); + } + + if (!err) { + [self reload]; + } +} + +// --------------------------------------------------------------------------- + +- (NSUInteger)minimumValidLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_minimum_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + +// --------------------------------------------------------------------------- + +- (NSUInteger)maximumValidLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_maximum_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + +// --------------------------------------------------------------------------- + +- (NSUInteger)minimumRenewableLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_minimum_renewal_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + +// --------------------------------------------------------------------------- + +- (NSUInteger)maximumRenewableLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_maximum_renewal_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KIMUtilities.h b/krb5-1-7/src/kim/agent/mac/KIMUtilities.h new file mode 100644 index 000000000..6575ca712 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KIMUtilities.h @@ -0,0 +1,101 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#import + +#define VALID_LIFETIME_INCREMENT (5 * 60) +#define RENEWABLE_LIFETIME_INCREMENT (15 * 60) + +#define client_name_keypath @"content.name" +#define client_path_keypath @"content.path" + +#define identity_string_keypath @"content.identity_string" +#define favorite_strings_keypath @"content.favorite_identity_strings" +#define title_keypath @"content.title" +#define message_keypath @"content.message" +#define description_keypath @"content.description" + +#define prompt_response_keypath @"content.prompt_response" +#define allow_save_password_keypath @"content.allow_save" +#define should_save_password_keypath @"content.save_response" + +#define password_expired_keypath @"content.expired" +#define old_password_keypath @"content.old_password" +#define new_password_keypath @"content.new_password" +#define verify_password_keypath @"content.verify_password" + +#define enable_identity_ok_keypath @"content.isPrincipalValid" +#define enable_prompt_ok_keypath @"content.isPromptValid" +#define change_password_ok_keypath @"content.isChangePasswordValid" + +#define options_keypath @"content.options" + +#define uses_default_options_keypath @"content.usesDefaultTicketOptions" +#define valid_lifetime_keypath @"content.valid_lifetime" +#define renewal_lifetime_keypath @"content.renewal_lifetime" +#define renewable_keypath @"content.renewable" +#define addressless_keypath @"content.addressless" +#define forwardable_keypath @"content.forwardable" + +#define min_valid_keypath @"content.minValidLifetime" +#define max_valid_keypath @"content.maxValidLifetime" +#define min_renewable_keypath @"content.minRenewableLifetime" +#define max_renewable_keypath @"content.maxRenewableLifetime" + +#define wants_change_password_keypath @"content.wants_change_password" +#define accepting_input_keypath @"content.acceptingInput" + +#define ACKVOContext @"authenticationController" + + + +#define log_kim_error_to_console(err)\ +{\ +NSLog(@"%s got error %@", __FUNCTION__, [KIMUtilities stringForLastKIMError:err]);\ +} while (0); + +@interface KIMUtilities : NSObject + ++ (NSString *) stringForLastKIMError: (kim_error) in_err; + ++ (BOOL) validatePrincipalWithName: (NSString *) name + realm: (NSString *) realm; + ++ (BOOL) validateIdentity: (NSString *) identityString; + ++ (NSString *) expandedIdentity: (NSString *) identityString; + ++ (NSDictionary *) dictionaryForKimOptions: (kim_options) options; ++ (kim_options) kimOptionsForDictionary: (NSDictionary *) aDict; + ++ (NSDictionary *) dictionaryForKimSelectionHints: (kim_selection_hints) hints; + ++ (NSUInteger)minValidLifetime; ++ (NSUInteger)maxValidLifetime; ++ (NSUInteger)minRenewableLifetime; ++ (NSUInteger)maxRenewableLifetime; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KIMUtilities.m b/krb5-1-7/src/kim/agent/mac/KIMUtilities.m new file mode 100644 index 000000000..320ccdd8e --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KIMUtilities.m @@ -0,0 +1,376 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "KIMUtilities.h" + +@implementation KIMUtilities + ++ (NSString *) stringForLastKIMError: (kim_error) in_err +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + NSString *result = nil; + + err = kim_string_create_for_last_error(&string, in_err); + if (!err) { + result = [NSString stringWithUTF8String:string]; + } + kim_string_free(&string); + + return result; +} + ++ (BOOL) validatePrincipalWithName: (NSString *) name + realm: (NSString *) realm +{ + kim_error err = KIM_NO_ERROR; + NSString *identityString = nil; + + if (!name || !realm || [name length] == 0) { + err = KIM_BAD_PRINCIPAL_STRING_ERR; + } + if (!err) { + identityString = [[NSString alloc] initWithFormat:@"%@@%@", name, realm]; + err = [KIMUtilities validateIdentity:identityString]; + [identityString release]; + } + + return (err == KIM_NO_ERROR); +} + ++ (BOOL) validateIdentity: (NSString *) identityString +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + if (!identityString || [identityString length] <= 1) { + err = KIM_BAD_PRINCIPAL_STRING_ERR; + } + if (!err) { + err = kim_identity_create_from_string(&identity, [identityString UTF8String]); + } + if (!identity) { + err = KIM_BAD_PRINCIPAL_STRING_ERR; + } + kim_identity_free(&identity); + + return (err == KIM_NO_ERROR); +} + ++ (NSString *) expandedIdentity: (NSString *) identityString +{ + NSString *result = nil; + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_string validated_string = NULL; + + // convert to how it will actually be + // e.g. foo becomes foo@ATHENA.MIT.EDU + // for the purpose of matching to a favorite + if (!identityString) { + err = KIM_BAD_PRINCIPAL_STRING_ERR; + } + if (!err) { + err = kim_identity_create_from_string(&identity, [identityString UTF8String]); + } + if (!err && identity) { + err = kim_identity_get_display_string(identity, &validated_string); + } + if (!err && validated_string) { + result = [NSString stringWithUTF8String:validated_string]; + } + kim_identity_free(&identity); + kim_string_free(&validated_string); + + return result; +} + ++ (NSDictionary *) dictionaryForKimOptions: (kim_options) options +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + NSMutableDictionary *newDict = [NSMutableDictionary dictionaryWithCapacity:8]; + kim_boolean addressless = FALSE; + kim_boolean forwardable = FALSE; + kim_boolean proxiable = FALSE; + kim_boolean renewable = FALSE; + kim_lifetime valid_lifetime = 0; + kim_lifetime renewal_lifetime = 0; + kim_string service_name = NULL; + kim_time start_time = 0; + + if (options == KIM_OPTIONS_DEFAULT) { + [newDict setObject:[NSNumber numberWithBool:YES] + forKey:@"usesDefaultTicketOptions"]; + err = kim_preferences_create(&prefs); + if (!err) { + err = kim_preferences_get_options(prefs, &options); + } + } + + if (!err) { + err = kim_options_get_addressless(options, &addressless); + } + if (!err) { + [newDict setValue:[NSNumber numberWithBool:addressless] + forKey:@"addressless"]; + } + if (!err) { + err = kim_options_get_forwardable(options, &forwardable); + } + if (!err) { + [newDict setValue:[NSNumber numberWithBool:forwardable] + forKey:@"forwardable"]; + } + if (!err) { + err = kim_options_get_proxiable(options, &proxiable); + } + if (!err) { + [newDict setValue:[NSNumber numberWithBool:proxiable] + forKey:@"proxiable"]; + } + if (!err) { + err = kim_options_get_renewable(options, &renewable); + } + if (!err) { + [newDict setValue:[NSNumber numberWithBool:renewable] + forKey:@"renewable"]; + } + if (!err) { + err = kim_options_get_lifetime(options, &valid_lifetime); + } + if (!err) { + [newDict setValue:[NSNumber numberWithInteger:valid_lifetime] + forKey:@"valid_lifetime"]; + } + if (!err) { + err = kim_options_get_renewal_lifetime(options, &renewal_lifetime); + } + if (!err) { + [newDict setValue:[NSNumber numberWithInteger:renewal_lifetime] + forKey:@"renewal_lifetime"]; + } + if (!err) { + err = kim_options_get_service_name(options, &service_name); + } + if (!err) { + [newDict setValue:(service_name) ? + [NSString stringWithUTF8String:service_name] : @"" + forKey:@"service_name"]; + } + if (!err) { + err = kim_options_get_start_time(options, &start_time); + } + if (!err) { + [newDict setValue:[NSNumber numberWithInteger:start_time] + forKey:@"start_time"]; + } + + // only free options if it was allocated by this method + if (prefs) { + kim_options_free(&options); + kim_preferences_free(&prefs); + } + + return newDict; +} + ++ (kim_options) kimOptionsForDictionary: (NSDictionary *) aDict +{ + kim_error err = KIM_NO_ERROR; + kim_options options = NULL; + kim_boolean addressless; + kim_boolean forwardable; + kim_boolean proxiable; + kim_boolean renewable; + kim_lifetime valid_lifetime; + kim_lifetime renewal_lifetime; + kim_string service_name; + kim_time start_time; + + if (!aDict || [[aDict objectForKey:@"usesDefaultTicketOptions"] boolValue]) { + return KIM_OPTIONS_DEFAULT; + } + + addressless = [[aDict valueForKey:@"addressless"] boolValue]; + forwardable = [[aDict valueForKey:@"forwardable"] boolValue]; + proxiable = [[aDict valueForKey:@"proxiable"] boolValue]; + renewable = [[aDict valueForKey:@"renewable"] boolValue]; + valid_lifetime = [[aDict valueForKey:@"valid_lifetime"] integerValue]; + renewal_lifetime = [[aDict valueForKey:@"renewal_lifetime"] integerValue]; + service_name = ([[aDict valueForKey:@"service_name"] length] > 0) ? + [[aDict valueForKey:@"service_name"] UTF8String] : NULL; + start_time = [[aDict valueForKey:@"start_time"] integerValue]; + + if (!err) { + err = kim_options_create (&options); + } + if (!err) { + err = kim_options_set_addressless(options, addressless); + } + if (!err) { + err = kim_options_set_forwardable(options, forwardable); + } + if (!err) { + err = kim_options_set_proxiable(options, proxiable); + } + if (!err) { + err = kim_options_set_renewable(options, renewable); + } + if (!err) { + err = kim_options_set_lifetime(options, valid_lifetime); + } + if (!err) { + err = kim_options_set_renewal_lifetime(options, renewal_lifetime); + } + if (!err) { + err = kim_options_set_service_name(options, service_name); + } + if (!err) { + err = kim_options_set_start_time(options, start_time); + } + + return options; +} + ++ (NSDictionary *) dictionaryForKimSelectionHints: (kim_selection_hints) hints +{ + kim_error err = KIM_NO_ERROR; + + NSMutableDictionary *newDict = [NSMutableDictionary dictionaryWithCapacity:20]; + + kim_string explanation = NULL; + kim_options options = NULL; + kim_string service_identity = NULL; + kim_string client_realm = NULL; + kim_string user = NULL; + kim_string service_realm = NULL; + kim_string service = NULL; + kim_string server = NULL; + + if (!err) { + err = kim_selection_hints_get_explanation(hints, &explanation); + [newDict setValue:(explanation) ? [NSString stringWithUTF8String:explanation] : @"" + forKey:@"explanation"]; + } + if (!err) { + err = kim_selection_hints_get_options(hints, &options); + [newDict setValue:[KIMUtilities dictionaryForKimOptions:options] + forKey:@"options"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_client_realm, &client_realm); + [newDict setValue:(client_realm) ? [NSString stringWithUTF8String:client_realm] : @"" + forKey:@"client_realm"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_user, &user); + [newDict setValue:(user) ? [NSString stringWithUTF8String:user] : @"" + forKey:@"user"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_service_realm, &service_realm); + [newDict setValue:(service_realm) ? [NSString stringWithUTF8String:service_realm] : @"" + forKey:@"service_realm"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_service, &service); + [newDict setValue:(service) ? [NSString stringWithUTF8String:service] : @"" + forKey:@"service"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_server, &server); + [newDict setValue:(server) ? [NSString stringWithUTF8String:server] : @"" + forKey:@"server"]; + } + if (!err) { + err = kim_selection_hints_get_hint(hints, kim_hint_key_service_identity, &service_identity); + [newDict setValue:(service_identity) ? [NSString stringWithUTF8String:service_identity] : @"" + forKey:@"service_identity"]; + } + + return newDict; +} + ++ (NSUInteger)minValidLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_minimum_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + ++ (NSUInteger)maxValidLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_maximum_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + ++ (NSUInteger)minRenewableLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_minimum_renewal_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + ++ (NSUInteger)maxRenewableLifetime +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_lifetime value = 0; + + err = kim_preferences_create(&prefs); + + if (!err) { + kim_preferences_get_maximum_renewal_lifetime(prefs, &value); + } + + return (NSUInteger) value; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgent-Info.plist b/krb5-1-7/src/kim/agent/mac/KerberosAgent-Info.plist new file mode 100644 index 000000000..ee304e6d5 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgent-Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + KerberosAgent + CFBundleIdentifier + edu.mit.Kerberos.KerberosAgent + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + KerberosAgent + CFBundlePackageType + APPL + CFBundleSignature + KrbA + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + LSUIElement + + + diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgentController.h b/krb5-1-7/src/kim/agent/mac/KerberosAgentController.h new file mode 100644 index 000000000..876961163 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgentController.h @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +@class IPCClient; +@class AuthenticationController; + +@interface KerberosAgentController : NSObject { + NSMutableArray *clients; + NSTimer *autoQuitTimer; +} + +@property (readwrite, retain) NSMutableArray *clients; + +- (void) quitIfIdle: (NSTimer *) timer; + +- (IPCClient *)clientForPort:(mach_port_t)client_port; +- (IPCClient *)clientForInfo:(NSDictionary *)info; + +- (IBAction) fakeANewClient: (id) sender; + +- (void) addClient: (NSDictionary *) info; +- (void) enterIdentity: (NSDictionary *) info; +- (void) selectIdentity: (NSDictionary *) info; +- (void) promptForAuth: (NSDictionary *) info; +- (void) changePassword: (NSDictionary *) info; +- (void) handleError: (NSDictionary *) info; +- (void) removeClient: (NSDictionary *) info; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgentController.m b/krb5-1-7/src/kim/agent/mac/KerberosAgentController.m new file mode 100644 index 000000000..e2314fcd6 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgentController.m @@ -0,0 +1,230 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "KerberosAgentController.h" +#import "SelectIdentityController.h" +#import "AuthenticationController.h" +#import "KerberosAgentListener.h" +#import "IPCClient.h" +#import "ServerDemux.h" + +#define SECONDS_BEFORE_AUTO_QUIT_ON_START 600 +#define SECONDS_BEFORE_AUTO_QUIT_ON_NO_CLIENTS 1 + +@implementation KerberosAgentController + +@synthesize clients; + +// --------------------------------------------------------------------------- + +- (void) applicationDidFinishLaunching: (NSNotification *) notification +{ + self.clients = [NSMutableArray array]; + [KerberosAgentListener startListening]; + + [NSApp activateIgnoringOtherApps:YES]; + + autoQuitTimer = [NSTimer scheduledTimerWithTimeInterval:SECONDS_BEFORE_AUTO_QUIT_ON_START + target:self + selector:@selector(quitIfIdle:) + userInfo:nil + repeats:NO]; +} + +- (void) dealloc +{ + self.clients = nil; + [autoQuitTimer invalidate]; + [autoQuitTimer release]; + + [super dealloc]; +} + +- (void) quitIfIdle: (NSTimer *) timer +{ + if ([self.clients count] == 0) { + [NSApp terminate:nil]; + } + autoQuitTimer = nil; +} + +- (IPCClient *)clientForPort:(mach_port_t)client_port +{ + IPCClient *aClient = nil; + + for (aClient in self.clients) { + if (aClient.port == client_port) { + break; + } + } + + return aClient; +} + +- (IPCClient *)clientForInfo:(NSDictionary *)info +{ + mach_port_t client_port = [[info objectForKey:@"client_port"] integerValue]; + return [self clientForPort:client_port]; +} + +- (IBAction) fakeANewClient: (id) sender +{ + IPCClient *aClient = [[IPCClient alloc] init]; + aClient.port = 1; + aClient.name = @"Barry"; + aClient.path = [[NSBundle mainBundle] bundlePath]; + [self.clients addObject:aClient]; + [aClient release]; +} + +#pragma mark Client actions + +// init +- (void) addClient: (NSDictionary *) info +{ + int32_t err = 0; + IPCClient *aClient = [self clientForInfo:info]; + + if (aClient) { + // already registered + err = KIM_IDENTITY_ALREADY_IN_LIST_ERR; + } else { + aClient = [[IPCClient alloc] init]; + aClient.port = [[info objectForKey:@"client_port"] integerValue]; + aClient.name = [info objectForKey:@"name"]; + aClient.path = [info objectForKey:@"path"]; + [self.clients addObject:aClient]; + [aClient release]; + } + + [autoQuitTimer invalidate]; + autoQuitTimer = nil; + + [KerberosAgentListener didAddClient:info error:err]; + [info release]; +} + +// enter +- (void) enterIdentity: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = nil; + + // get client object for matching info, creating if it doesn't exist + aClient = [self clientForInfo:info]; + if (!aClient) { err = KIM_IDENTITY_NOT_IN_LIST_ERR; } + else { + err = [aClient enterIdentity:info]; + } + if (err) { + [KerberosAgentListener didEnterIdentity:info error:err]; + } +} + +// select +- (void) selectIdentity: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = nil; + + // get client object for matching info, creating if it doesn't exist + aClient = [self clientForInfo:info]; + if (!aClient) { err = KIM_IDENTITY_NOT_IN_LIST_ERR; } + else { + err = [aClient selectIdentity:info]; + } + if (err) { + [KerberosAgentListener didSelectIdentity:info error:err]; + } +} + +// auth +- (void) promptForAuth: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = nil; + + aClient = [self clientForInfo:info]; + if (!aClient) { err = KIM_IDENTITY_NOT_IN_LIST_ERR; } + else { + err = [aClient promptForAuth:info]; + } +} + +// change password +- (void) changePassword: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = nil; + + aClient = [self clientForInfo:info]; + if (!aClient) { err = KIM_IDENTITY_NOT_IN_LIST_ERR; } + else { + err = [aClient changePassword:info]; + } +} + +// error +- (void) handleError: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = nil; + + aClient = [self clientForInfo:info]; + if (!aClient) { err = KIM_IDENTITY_NOT_IN_LIST_ERR; } + else { + err = [aClient handleError:info]; + } +} + +// fini +- (void) removeClient: (NSDictionary *) info +{ + kim_error err = KIM_NO_ERROR; + IPCClient *aClient = [self clientForInfo:info]; + + if (!aClient) { + err = KIM_IDENTITY_NOT_IN_LIST_ERR; + } else { + // close all windows associated with it + [aClient cleanup]; + [self.clients removeObject:aClient]; + if ([self.clients count] == 0) { + // the client removes itself after select identity, + // but might come back shortly afterward in need of an auth prompt + [autoQuitTimer invalidate]; + autoQuitTimer = [NSTimer scheduledTimerWithTimeInterval:SECONDS_BEFORE_AUTO_QUIT_ON_NO_CLIENTS + target:self + selector:@selector(quitIfIdle:) + userInfo:nil + repeats:NO]; + } + } + + // called after user finishes prompt + [KerberosAgentListener didRemoveClient:info error:err]; + [info release]; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.h b/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.h new file mode 100644 index 000000000..2d9378aff --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.h @@ -0,0 +1,109 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#import + +#define kCheckinMessage 100 + +@interface KerberosAgentListener : NSObject { + NSThread *thread; +} + +@property (readwrite, retain) NSThread *thread; + ++ (KerberosAgentListener *) sharedListener; + ++ (void) startListening; + +- (void) threadMain; + ++ (void) addClientWithPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + name: (kim_string) name + path: (kim_string) path; + +// contains reply_port ++ (void) didAddClient: (NSDictionary *) info + error: (int32_t) error; + ++ (void) enterIdentityWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + options: (kim_options) options; + +// contains reply_port, kim_identity ++ (void) didEnterIdentity: (NSDictionary *) info + error: (int32_t) error; + ++ (void) selectIdentityWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + hints: (kim_selection_hints) hints; + +// contains reply_port, kim_identity ++ (void) didSelectIdentity: (NSDictionary *) info + error: (int32_t) error; + ++ (void) promptForAuthWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + promptType: (uint32_t) prompt_type + allowSave: (kim_boolean) allow_save + hideReply: (kim_boolean) hide_reply + title: (kim_string) title + message: (kim_string) message + description: (kim_string) description; + +// contains reply_port, (string) prompt_response ++ (void) didPromptForAuth: (NSDictionary *) info + error: (int32_t) error; + ++ (void) changePasswordWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + expired: (kim_boolean) expired; + +// contains reply_port, old password, new password, verify password ++ (void) didChangePassword: (NSDictionary *) info + error: (int32_t) error; + ++ (void) handleErrorWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + error: (kim_error) error + message: (kim_string) message + description: (kim_string) description; + +// contains reply_port ++ (void) didHandleError: (NSDictionary *) info + error: (int32_t) error; + + ++ (void) removeClientMatchingPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port; + ++ (void) didRemoveClient: (NSDictionary *)info + error: (int32_t) error; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.m b/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.m new file mode 100644 index 000000000..6c4c8d7c8 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgentListener.m @@ -0,0 +1,355 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "KerberosAgentListener.h" +#import "KIMUtilities.h" +#import "ServerDemux.h" +#import "IPCClient.h" + +@implementation KerberosAgentListener + +@synthesize thread; + +- (id) init +{ + self = [super init]; + if (self != nil) { + self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain) object:nil]; + } + return self; +} + +static KerberosAgentListener *sharedListener = nil; + ++ (KerberosAgentListener *) sharedListener +{ + @synchronized(self) { + if (sharedListener == nil) { + [[self alloc] init]; // assignment not done here + } + } + return sharedListener; +} + ++ (id)allocWithZone:(NSZone *)zone +{ + @synchronized(self) { + if (sharedListener == nil) { + sharedListener = [super allocWithZone:zone]; + return sharedListener; // assignment and return on first allocation + } + } + return nil; //on subsequent allocation attempts return nil +} + +- (id)copyWithZone:(NSZone *)zone +{ + return self; +} + +- (id)retain +{ + return self; +} + +- (unsigned)retainCount +{ + return UINT_MAX; //denotes an object that cannot be released +} + +- (void)release +{ + //do nothing +} + +- (id)autorelease +{ + return self; +} + +#pragma mark Thread management + +// called from main thread to start listen thread ++ (void) startListening +{ +// NSLog(@"%s %@ thread", __FUNCTION__, ([NSThread isMainThread]) ? @"main" : @"not main"); + + [[KerberosAgentListener sharedListener].thread start]; +} + +- (void) threadMain +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int32_t err = 0; + +// NSLog(@"%s starting up", __FUNCTION__); + + while (!err && ![self.thread isCancelled]) { + err = kim_agent_listen_loop(); + if (!err) { +// NSLog (@"%s loop resetting %@", __FUNCTION__, [[NSThread currentThread] description]); + } else { + NSLog (@"%s got error %d (%@) %@", __FUNCTION__, err, [KIMUtilities stringForLastKIMError:err], [[NSThread currentThread] description]); + err = 0; /* The server quit unexpectedly -- just try again */ + } + sleep(10); + } + + [pool release]; +} + +#pragma mark IPC handlers + ++ (void) addClientWithPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + name: (kim_string) name + path: (kim_string) path +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [NSString stringWithUTF8String:name], @"name", + [NSString stringWithUTF8String:path], @"path", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(addClient:) + withObject:info + waitUntilDone:NO]; +} + ++ (void) didAddClient: (NSDictionary *) info + error: (kim_error) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + err = kim_handle_reply_init(reply_port, error); +} + ++ (void) enterIdentityWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + options: (kim_options) options +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [KIMUtilities dictionaryForKimOptions:options], @"options", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(enterIdentity:) + withObject:info + waitUntilDone:NO]; +} + +// contains reply_port, identity_string ++ (void) didEnterIdentity: (NSDictionary *) info + error: (kim_error) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + NSString *identityString = [info objectForKey:@"identity_string"]; + kim_identity identity = NULL; + kim_options options = NULL; + BOOL wants_change_password = [[info objectForKey:@"wants_change_password"] boolValue]; + + if (identityString) { + err = kim_identity_create_from_string (&identity, [identityString UTF8String]); + } + + if (!err) { + options = [KIMUtilities kimOptionsForDictionary:[info objectForKey:@"options"]]; + + } + + if (!err) { + err = kim_handle_reply_enter_identity(reply_port, identity, options, wants_change_password, error); + } + + kim_options_free (&options); +} + ++ (void) selectIdentityWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + hints: (kim_selection_hints) hints +{ + NSDictionary *info = nil; + + info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [KIMUtilities dictionaryForKimSelectionHints:hints], @"hints", + nil]; + + [[NSApp delegate] performSelectorOnMainThread:@selector(selectIdentity:) + withObject:info + waitUntilDone:NO]; +} + +// contains reply_port, identity_string ++ (void) didSelectIdentity: (NSDictionary *) info + error: (int32_t) error +{ + kim_error err = KIM_NO_ERROR; + NSNumber *portNumber = [info objectForKey:@"reply_port"]; + NSString *identityString = [info objectForKey:@"identity_string"]; + mach_port_t reply_port = [portNumber integerValue]; + kim_identity identity = NULL; + kim_options options = NULL; + BOOL wants_change_password = [[info objectForKey:@"wants_change_password"] boolValue]; + + if (identityString) { + err = kim_identity_create_from_string(&identity, [identityString UTF8String]); + } + + if (!err) { + options = [KIMUtilities kimOptionsForDictionary:[info objectForKey:@"options"]]; + } + + if (!err) { + err = kim_handle_reply_select_identity(reply_port, identity, options, wants_change_password, error); + } + + kim_options_free (&options); +} + ++ (void) promptForAuthWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + promptType: (uint32_t) prompt_type + allowSave: (kim_boolean) allow_save + hideReply: (kim_boolean) hide_reply + title: (kim_string) title + message: (kim_string) message + description: (kim_string) description +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [NSString stringWithUTF8String:identity_string], @"identity_string", + [NSNumber numberWithUnsignedInt:prompt_type], @"prompt_type", + [NSNumber numberWithBool:allow_save], @"allow_save", + [NSNumber numberWithBool:hide_reply], @"hide_reply", + [NSString stringWithUTF8String:title], @"title", + [NSString stringWithUTF8String:message], @"message", + [NSString stringWithUTF8String:description], @"description", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(promptForAuth:) + withObject:info + waitUntilDone:NO]; +} + +// contains reply_port, (string) prompt_response ++ (void) didPromptForAuth: (NSDictionary *) info + error: (int32_t) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + kim_string prompt_response = [[info objectForKey:@"prompt_response"] UTF8String]; + kim_boolean save_response = [[info objectForKey:@"save_response"] boolValue]; + + err = kim_handle_reply_auth_prompt(reply_port, prompt_response, save_response, error); +} + ++ (void) changePasswordWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + expired: (kim_boolean) expired +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [NSString stringWithUTF8String:identity_string], @"identity_string", + [NSNumber numberWithBool:expired], @"expired", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(changePassword:) + withObject:info + waitUntilDone:NO]; +} + +// contains reply_port, old password, new password, verify password ++ (void) didChangePassword: (NSDictionary *) info + error: (int32_t) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + kim_string old_pw = [[info objectForKey:@"old_password"] UTF8String]; + kim_string new_pw = [[info objectForKey:@"new_password"] UTF8String]; + kim_string verify_pw = [[info objectForKey:@"verify_password"] UTF8String]; + + err = kim_handle_reply_change_password(reply_port, old_pw, new_pw, verify_pw, error); +} + ++ (void) handleErrorWithClientPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port + identity: (kim_string) identity_string + error: (kim_error) error + message: (kim_string) message + description: (kim_string) description +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + [NSString stringWithUTF8String:identity_string], @"identity_string", + [NSNumber numberWithUnsignedInt:error], @"error", + [NSString stringWithUTF8String:message], @"message", + [NSString stringWithUTF8String:description], @"description", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(handleError:) + withObject:info + waitUntilDone:NO]; + +} + +// contains reply_port ++ (void) didHandleError: (NSDictionary *) info + error: (int32_t) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + + err = kim_handle_reply_handle_error(reply_port, error); +} + ++ (void) removeClientMatchingPort: (mach_port_t) client_port + replyPort: (mach_port_t) reply_port +{ + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInteger:client_port], @"client_port", + [NSNumber numberWithInteger:reply_port], @"reply_port", + nil]; + [[NSApp delegate] performSelectorOnMainThread:@selector(removeClient:) + withObject:info + waitUntilDone:NO]; +} + +// contains reply_port ++ (void) didRemoveClient: (NSDictionary *)info + error: (int32_t) error +{ + kim_error err = KIM_NO_ERROR; + mach_port_t reply_port = [[info objectForKey:@"reply_port"] integerValue]; + if (reply_port) { + err = kim_handle_reply_fini(reply_port, error); + } +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosAgentPrefix.pch b/krb5-1-7/src/kim/agent/mac/KerberosAgentPrefix.pch new file mode 100644 index 000000000..d919a4f0b --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosAgentPrefix.pch @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import + +#define CacheCollectionDidChangeNotification @"CacheCollectionDidChange" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/krb5-1-7/src/kim/agent/mac/KerberosFormatters.h b/krb5-1-7/src/kim/agent/mac/KerberosFormatters.h new file mode 100644 index 000000000..104ea5f42 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosFormatters.h @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + + +@interface KerberosTimeFormatter : NSFormatter { + BOOL displaySeconds; + BOOL displayShortFormat; +} + +@property BOOL displaySeconds; +@property BOOL displayShortFormat; + +- (NSString *)stringForObjectValue:(id)anObject; + +- (NSAttributedString *)attributedStringForObjectValue:(id)anObject + withDefaultAttributes:(NSDictionary *)attributes; + +- (NSString *) stringForLifetime: (time_t) lifetime; + +@end + +@interface KerberosFavoriteFormatter : NSFormatter { + +} + +- (NSString *)stringForObjectValue:(id)anObject; + +- (NSAttributedString *)attributedStringForObjectValue:(id)anObject + withDefaultAttributes:(NSDictionary *)attributes; +@end diff --git a/krb5-1-7/src/kim/agent/mac/KerberosFormatters.m b/krb5-1-7/src/kim/agent/mac/KerberosFormatters.m new file mode 100644 index 000000000..dc4092140 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/KerberosFormatters.m @@ -0,0 +1,174 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "KerberosFormatters.h" + +@implementation KerberosTimeFormatter + +@synthesize displaySeconds; +@synthesize displayShortFormat; + +- (id) init +{ + self = [super init]; + if (self != nil) { + // default to --:-- style + self.displaySeconds = NO; + self.displayShortFormat = YES; + } + return self; +} + +/* + * For display of Kerberos expiration times. + * Converts an NSDate into an NSString like "09:53" for 9 hours and 53 minutes + * in the future. Returns @"Expired" if expiration date is before now. + */ +- (NSString *)stringForObjectValue:(id)anObject +{ + NSString *result = nil; + + if (anObject) { + if ([anObject respondsToSelector:@selector(timeIntervalSinceNow)]) { + result = [self stringForLifetime:(time_t)[(NSDate *)anObject timeIntervalSinceNow]]; + } + else if ([anObject respondsToSelector:@selector(unsignedIntegerValue)]) { + result = [self stringForLifetime:(time_t)[(NSNumber *)anObject unsignedIntegerValue]]; + } + } + + return result; +} + +- (NSAttributedString *)attributedStringForObjectValue:(id)anObject + withDefaultAttributes:(NSDictionary *)attributes +{ + return [[[NSAttributedString alloc] initWithString:[self stringForObjectValue:anObject] + attributes:attributes] autorelease]; +} + +- (NSString *) stringForLifetime: (time_t) lifetime +{ + NSMutableString *string = [NSMutableString string]; + NSString *separatorKey = (self.displayShortFormat) ? @"LifetimeStringSeparatorShortFormat" : + @"LifetimeStringSeparatorLongFormat"; + NSString *separator = NSLocalizedStringFromTable (separatorKey, @"KerberosFormatters", NULL); + NSString *key = NULL; + + // Break the lifetime up into time units + time_t days = (lifetime / 86400); + time_t hours = (lifetime / 3600 % 24); + time_t minutes = (lifetime / 60 % 60); + time_t seconds = (lifetime % 60); + + if (lifetime > 0) { + // If we aren't going to display seconds, round up + if (!self.displaySeconds) { + if (seconds > 0) { seconds = 0; minutes++; } + if (minutes > 59) { minutes = 0; hours++; } + if (hours > 23) { hours = 0; days++; } + } + + if (days > 0 && !self.displayShortFormat) { + if (self.displayShortFormat) { + key = (days > 1) ? @"LifetimeStringDaysShortFormat" : @"LifetimeStringDayShortFormat"; + } else { + key = (days > 1) ? @"LifetimeStringDaysLongFormat" : @"LifetimeStringDayLongFormat"; + } + [string appendFormat: NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL), days]; + } + + if ((hours > 0) || self.displayShortFormat) { + if (self.displayShortFormat) { + key = (hours > 1) ? @"LifetimeStringHoursShortFormat" : @"LifetimeStringHourShortFormat"; + hours += days * 24; + days = 0; + } else { + key = (hours > 1) ? @"LifetimeStringHoursLongFormat" : @"LifetimeStringHourLongFormat"; + } + if ([string length] > 0) { [string appendString: separator]; } + [string appendFormat: NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL), hours]; + } + + if ((minutes > 0) || self.displayShortFormat) { + if (self.displayShortFormat) { + key = (minutes > 1) ? @"LifetimeStringMinutesShortFormat" : @"LifetimeStringMinuteShortFormat"; + } else { + key = (minutes > 1) ? @"LifetimeStringMinutesLongFormat" : @"LifetimeStringMinuteLongFormat"; + } + if ([string length] > 0) { [string appendString: separator]; } + [string appendFormat: NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL), minutes]; + } + + if (self.displaySeconds && ((seconds > 0) || self.displayShortFormat)) { + if (self.displayShortFormat) { + key = (seconds > 1) ? @"LifetimeStringSecondsShortFormat" : @"LifetimeStringSecondShortFormat"; + } else { + key = (seconds > 1) ? @"LifetimeStringSecondsLongFormat" : @"LifetimeStringSecondLongFormat"; + } + if ([string length] > 0) { [string appendString: separator]; } + [string appendFormat: NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL), seconds]; + } + } else { + key = @"LifetimeStringExpired"; + [string appendString: NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL)]; + } + + // Return an NSString (non-mutable) from our mutable temporary + return [NSString stringWithString: string]; +} + +@end + +@implementation KerberosFavoriteFormatter + +/* + * For displaying favorite status of KIM identities. + * Converts an NSNumber containing a boolean value into an NSString. + * If true, returns a heart character, /u2665. + * If false, returns empty string @"". + */ +- (NSString *)stringForObjectValue:(id)anObject +{ + NSString *key = nil; + if (anObject == nil || + ![anObject respondsToSelector:@selector(boolValue)] || + ([(NSNumber *)anObject boolValue] == FALSE)) { + key = @"FavoriteStringNotFavorite"; + } + else { + key = @"FavoriteStringIsFavorite"; + } + + return NSLocalizedStringFromTable (key, @"KerberosFormatters", NULL); +} + +- (NSAttributedString *)attributedStringForObjectValue:(id)anObject + withDefaultAttributes:(NSDictionary *)attributes +{ + return [[[NSAttributedString alloc] initWithString:[self stringForObjectValue:anObject] + attributes:attributes] autorelease]; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/PopupButton.h b/krb5-1-7/src/kim/agent/mac/PopupButton.h new file mode 100644 index 000000000..5ced9513e --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/PopupButton.h @@ -0,0 +1,34 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + + +@interface PopupButton : NSButton { + +} + +- (void) mouseDown: (NSEvent *) event; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/PopupButton.m b/krb5-1-7/src/kim/agent/mac/PopupButton.m new file mode 100644 index 000000000..d264c041b --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/PopupButton.m @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "PopupButton.h" + + +@implementation PopupButton + +// --------------------------------------------------------------------------- + +- (void) mouseDown: (NSEvent *) event +{ + if([self isEnabled] && ([self menu] != NULL)) { + NSEvent *menuEvent = NULL; + NSPoint menuPoint = { 3, [self frame].size.height + 1 }; + + [self highlight: YES]; + + menuEvent = [NSEvent mouseEventWithType: [event type] + location: [self convertPoint: menuPoint toView: NULL] + modifierFlags: [event modifierFlags] + timestamp: [event timestamp] + windowNumber: [[event window] windowNumber] + context: [event context] + eventNumber: [event eventNumber] + clickCount: [event clickCount] + pressure: [event pressure]]; + + [NSMenu popUpContextMenu: [self menu] withEvent: menuEvent forView: self]; + + [self highlight: NO]; + } else { + [super mouseDown: event]; + } +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/SelectIdentityController.h b/krb5-1-7/src/kim/agent/mac/SelectIdentityController.h new file mode 100644 index 000000000..4d744ba08 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/SelectIdentityController.h @@ -0,0 +1,98 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#import "BadgedImageView.h" +#import "Identities.h" + +@class IPCClient; +@class KerberosTimeFormatter; + +@interface SelectIdentityController : NSWindowController { + IPCClient *associatedClient; + + IBOutlet KerberosTimeFormatter *shortTimeFormatter; + IBOutlet KerberosTimeFormatter *longTimeFormatter; + + IBOutlet NSObjectController *identitiesController; + IBOutlet NSArrayController *identityArrayController; + + IBOutlet BadgedImageView *kerberosIconImageView; + IBOutlet NSTextField *headerTextField; + IBOutlet NSTextField *explanationTextField; + + IBOutlet NSScrollView *identityTableScrollView; + IBOutlet NSTableView *identityTableView; + IBOutlet NSButton *addIdentityButton; + IBOutlet NSPopUpButton *actionPopupButton; + IBOutlet NSButton *selectIdentityButton; + IBOutlet NSButton *cancelButton; + + Identities *identities; + NSTimer *refreshTimer; + + IBOutlet NSObjectController *glueController; + + IBOutlet NSWindow *ticketOptionsWindow; + IBOutlet NSObjectController *identityOptionsController; + IBOutlet NSTextField *identityField; + IBOutlet NSTextField *staticIdentityField; + + IBOutlet NSSlider *validLifetimeSlider; + IBOutlet NSSlider *renewableLifetimeSlider; + + IBOutlet NSBox *ticketOptionsBox; + IBOutlet NSButton *ticketOptionsOkButton; + IBOutlet NSButton *ticketOptionsToggleButton; + CGFloat optionsBoxHeight; +} + +@property (readwrite, retain) IPCClient *associatedClient; + +- (void) setContent: (NSMutableDictionary *) newContent; + +- (IBAction) newIdentity: (id) sender; +- (IBAction) addToFavorites: (id) sender; +- (IBAction) removeFromFavorites: (id) sender; + +- (IBAction) editOptions: (id) sender; +- (IBAction) cancelOptions: (id) sender; +- (IBAction) doneOptions: (id) sender; + +- (IBAction) changePassword: (id) sender; + +- (IBAction) select: (id) sender; +- (IBAction) cancel: (id) sender; + +- (IBAction) checkboxDidChange: (id) sender; +- (IBAction) sliderDidChange: (id) sender; + +- (void) showOptions: (NSString *) contextInfo; +- (void) didEndSheet: (NSWindow *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; +- (void) saveOptions; +- (IBAction) toggleOptionsVisibility: (id) sender; + +- (void) timedRefresh:(NSTimer *)timer; + +@end diff --git a/krb5-1-7/src/kim/agent/mac/SelectIdentityController.m b/krb5-1-7/src/kim/agent/mac/SelectIdentityController.m new file mode 100644 index 000000000..757848ab1 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/SelectIdentityController.m @@ -0,0 +1,410 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "SelectIdentityController.h" +#import "IPCClient.h" +#import "KerberosFormatters.h" + +@implementation SelectIdentityController + +@synthesize associatedClient; + +// --------------------------------------------------------------------------- + +- (id) init +{ + return [self initWithWindowNibName: @"SelectIdentity"]; +} + +// --------------------------------------------------------------------------- + +- (void) dealloc +{ + [identityOptionsController removeObserver:self forKeyPath:identity_string_keypath]; + [refreshTimer release]; + [identities release]; + [super dealloc]; +} + +// --------------------------------------------------------------------------- + +- (void) awakeFromNib +{ + NSString *key = nil; + NSString *message = nil; + + [[self window] center]; + [[self window] setLevel:NSModalPanelWindowLevel]; + + longTimeFormatter.displaySeconds = NO; + longTimeFormatter.displayShortFormat = NO; + + [identityTableView setDoubleAction:@selector(select:)]; + identities = [[Identities alloc] init]; + [identitiesController setContent:identities]; + refreshTimer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(timedRefresh:) userInfo:nil repeats:true]; + + [kerberosIconImageView setBadgePath:associatedClient.path]; + + if ([associatedClient.name isEqualToString:[[NSBundle mainBundle] bundlePath]]) { + key = @"SelectIdentityRequest"; + message = NSLocalizedStringFromTable(key, @"SelectIdentity", NULL); + } + else { + key = @"SelectIdentityApplicationRequest"; + message = [NSString stringWithFormat: + NSLocalizedStringFromTable(key, @"SelectIdentity", NULL), + associatedClient.name]; + } + [headerTextField setStringValue:message]; + + optionsBoxHeight = [ticketOptionsBox frame].size.height + [ticketOptionsBox frame].origin.y - [ticketOptionsToggleButton frame].origin.y - [ticketOptionsToggleButton frame].size.height; + [self toggleOptionsVisibility:nil]; + + [identityOptionsController addObserver:self + forKeyPath:identity_string_keypath + options:NSKeyValueObservingOptionNew + context:NULL]; +} + +- (void) observeValueForKeyPath:(NSString *) keyPath ofObject: (id) object change: (NSDictionary *) change context:(void *) context +{ + if (object == identityOptionsController && [keyPath isEqualToString:identity_string_keypath]) { + BOOL enabled = [KIMUtilities validateIdentity:[identityOptionsController valueForKeyPath:identity_string_keypath]]; + [identityOptionsController setValue:[NSNumber numberWithBool:enabled] + forKeyPath:@"content.canClickOK"]; + } + else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +// --------------------------------------------------------------------------- + +- (NSRect) windowWillUseStandardFrame: (NSWindow *) window defaultFrame: (NSRect) defaultFrame +{ + NSRect newFrame = [window frame]; + CGFloat oldHeight = [[identityTableScrollView contentView] frame].size.height; + CGFloat newHeight = [identityTableView numberOfRows] * + ([identityTableView rowHeight] + [identityTableView intercellSpacing].height); + CGFloat yDelta = newHeight - oldHeight; + + newFrame.origin.y -= yDelta; + newFrame.size.height += yDelta; + + return newFrame; +} + +// --------------------------------------------------------------------------- + +- (void) setContent: (NSMutableDictionary *) newContent +{ + [self window]; // wake up the nib connections + [glueController setContent:newContent]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) newIdentity: (id) sender +{ + identityOptionsController.content = [[[glueController valueForKeyPath:@"content.hints.options"] + mutableCopy] autorelease]; + + [self showOptions:@"new"]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) addToFavorites: (id) sender +{ + Identity *anIdentity = [identityArrayController.selectedObjects lastObject]; + identityOptionsController.content = nil; + + anIdentity.favorite = TRUE; + + [self saveOptions]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) removeFromFavorites: (id) sender +{ + Identity *anIdentity = [identityArrayController.selectedObjects lastObject]; + identityOptionsController.content = nil; + + anIdentity.favorite = FALSE; + + [self saveOptions]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) changePassword: (id) sender +{ + Identity *selectedIdentity = nil; + + // ignore double-click on header + if ([sender respondsToSelector:@selector(clickedRow)] && [sender clickedRow] < 0) { + return; + } + selectedIdentity = [[identityArrayController selectedObjects] lastObject]; + + [associatedClient didSelectIdentity: selectedIdentity.identity + options: [identityOptionsController valueForKeyPath:@"content.options"] + wantsChangePassword: YES]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) select: (id) sender +{ + Identity *selectedIdentity = nil; + + // ignore double-click on header + if ([sender respondsToSelector:@selector(clickedRow)] && [sender clickedRow] < 0) { + return; + } + selectedIdentity = [[identityArrayController selectedObjects] lastObject]; + + [associatedClient didSelectIdentity: selectedIdentity.identity + options: [identityOptionsController content] + wantsChangePassword: NO]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) cancel: (id) sender +{ + [associatedClient didCancel]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) editOptions: (id) sender +{ + Identity *anIdentity = [identityArrayController.selectedObjects lastObject]; + anIdentity.favorite = TRUE; + + [identityOptionsController setContent:anIdentity.options]; + + [self showOptions:@"edit"]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) cancelOptions: (id) sender +{ + identityOptionsController.content = nil; + [NSApp endSheet:ticketOptionsWindow returnCode:NSUserCancelledError]; + + // dump changed settings + [identities reload]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) doneOptions: (id) sender +{ +// Identity *anIdentity = identityOptionsController.content; + + + [NSApp endSheet: ticketOptionsWindow]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) checkboxDidChange: (id) sender +{ + if ([[identityOptionsController valueForKeyPath:uses_default_options_keypath] boolValue]) { + // merge defaults onto current options + NSMutableDictionary *currentOptions = [identityOptionsController content]; + NSDictionary *defaultOptions = [KIMUtilities dictionaryForKimOptions:NULL]; + NSLog(@"using default ticket options"); + [currentOptions addEntriesFromDictionary:defaultOptions]; + // update the sliders, since their values aren't bound + [validLifetimeSlider setDoubleValue:[[identityOptionsController valueForKeyPath:valid_lifetime_keypath] doubleValue]]; + [renewableLifetimeSlider setDoubleValue:[[identityOptionsController valueForKeyPath:renewal_lifetime_keypath] doubleValue]]; + } +} + +// --------------------------------------------------------------------------- + +- (IBAction) sliderDidChange: (id) sender +{ + NSInteger increment = 0; + NSInteger newValue = 0; + NSString *keyPath = nil; + if ([sender isEqual:validLifetimeSlider]) { + increment = VALID_LIFETIME_INCREMENT; + keyPath = valid_lifetime_keypath; + } + else if ([sender isEqual:renewableLifetimeSlider]) { + increment = RENEWABLE_LIFETIME_INCREMENT; + keyPath = renewal_lifetime_keypath; + } + if (increment > 0) { + newValue = ([sender integerValue] / increment) * increment; + [identityOptionsController setValue:[NSNumber numberWithInteger: + (newValue < increment) ? increment : newValue] + forKeyPath:keyPath]; + } +} + +// --------------------------------------------------------------------------- + +- (void) showOptions: (NSString *) contextInfo +{ + Identity *anIdentity = [[identityArrayController selectedObjects] lastObject]; + BOOL isIdentityNameNotEditable = (!anIdentity.hasCCache || [contextInfo isEqualToString:@"new"]); + NSString *identityString = ([contextInfo isEqualToString:@"new"]) ? @"" : anIdentity.identity; + + [identityOptionsController setValue:identityString + forKeyPath:identity_string_keypath]; + [identityOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities minValidLifetime]] + forKeyPath:min_valid_keypath]; + [identityOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities maxValidLifetime]] + forKeyPath:max_valid_keypath]; + [identityOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities minRenewableLifetime]] + forKeyPath:min_renewable_keypath]; + [identityOptionsController setValue:[NSNumber numberWithInteger:[KIMUtilities maxRenewableLifetime]] + forKeyPath:max_renewable_keypath]; + [identityOptionsController setValue:[NSNumber numberWithBool:!isIdentityNameNotEditable] + forKeyPath:@"content.hasCCache"]; + + [validLifetimeSlider setIntegerValue: + [[identityOptionsController valueForKeyPath:valid_lifetime_keypath] integerValue]]; + [renewableLifetimeSlider setIntegerValue: + [[identityOptionsController valueForKeyPath:renewal_lifetime_keypath] integerValue]]; + [self sliderDidChange:validLifetimeSlider]; + [self sliderDidChange:renewableLifetimeSlider]; + + [NSApp beginSheet: ticketOptionsWindow + modalForWindow: [self window] + modalDelegate: self + didEndSelector: @selector(didEndSheet:returnCode:contextInfo:) + contextInfo: contextInfo]; +} + +// --------------------------------------------------------------------------- + +- (void) didEndSheet: (NSWindow *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + kim_error err = KIM_NO_ERROR; + if (returnCode != NSUserCancelledError) { + if ([(NSString *)contextInfo isEqualToString:@"new"]) { + Identity *newIdentity = [[Identity alloc] + initWithIdentity:[identityOptionsController valueForKeyPath:identity_string_keypath] + options:identityOptionsController.content]; + newIdentity.favorite = YES; + + err = [identities addIdentity:newIdentity]; + + if (err) { + NSLog(@"%s received error %@ trying to add identity %@", _cmd, [KIMUtilities stringForLastKIMError:err], [newIdentity description]); + } + [newIdentity release]; + [self saveOptions]; + + } + else if ([(NSString *)contextInfo isEqualToString:@"edit"]) { + Identity *editedIdentity = [[identityArrayController selectedObjects] lastObject]; + editedIdentity.favorite = YES; + editedIdentity.identity = [identityOptionsController valueForKeyPath:identity_string_keypath]; + editedIdentity.options = identityOptionsController.content; + + [self saveOptions]; + + } + } else { + [identityOptionsController setContent:nil]; + } + [sheet orderOut:self]; + +} + +// --------------------------------------------------------------------------- + +- (void) saveOptions +{ + // attempt to preserve the selection + Identity *anIdentity = [[identityArrayController selectedObjects] lastObject]; + NSUInteger a, b, c; + + a = [identityArrayController.content indexOfObject: anIdentity]; + b = NSNotFound; + + [identities synchronizePreferences]; + + /* + * select same object as before if it's still in the array + * if not, select same index as before or end of array, whichever is less + */ + + b = [identityArrayController.content indexOfObject:anIdentity]; + c = [identityArrayController.content count] - 1; + + + [identityArrayController setSelectionIndex: (b == NSNotFound) ? (a > c) ? c : a : b]; +} + +// --------------------------------------------------------------------------- + +- (IBAction) toggleOptionsVisibility: (id) sender +{ + NSRect newFrame = [NSWindow contentRectForFrameRect:[ticketOptionsWindow frame] styleMask:[ticketOptionsWindow styleMask]]; + CGFloat newHeight; + + if ([ticketOptionsBox isHidden]) { + newHeight = newFrame.size.height + optionsBoxHeight; + newFrame.origin.y += newFrame.size.height; + newFrame.origin.y -= newHeight; + newFrame.size.height = newHeight; + newFrame = [NSWindow frameRectForContentRect:newFrame styleMask:[ticketOptionsWindow styleMask]]; + + [ticketOptionsWindow setFrame:newFrame display:YES animate:YES]; + [ticketOptionsBox setHidden:NO]; + [sender setTitle:NSLocalizedStringFromTable(@"SelectIdentityHideOptions", @"SelectIdentity", NULL)]; + } + else { + newHeight = newFrame.size.height - optionsBoxHeight; + newFrame.origin.y += newFrame.size.height; + newFrame.origin.y -= newHeight; + newFrame.size.height = newHeight; + newFrame = [NSWindow frameRectForContentRect:newFrame styleMask:[ticketOptionsWindow styleMask]]; + + [ticketOptionsBox setHidden:YES]; + [ticketOptionsWindow setFrame:newFrame display:YES animate:YES]; + [sender setTitle:NSLocalizedStringFromTable(@"SelectIdentityShowOptions", @"SelectIdentity", NULL)]; + } +} + +// --------------------------------------------------------------------------- + +- (void) timedRefresh:(NSTimer *)timer +{ + // refetch data to update expiration times + [identityArrayController rearrangeObjects]; +} + +@end diff --git a/krb5-1-7/src/kim/agent/mac/ServerDemux.h b/krb5-1-7/src/kim/agent/mac/ServerDemux.h new file mode 100644 index 000000000..39fd28107 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/ServerDemux.h @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5_mig_requestServer.h" +#import "k5_mig_reply.h" +#import "k5-ipc_stream.h" +#import "k5_mig_server.h" + + +int32_t kim_agent_listen_loop (void); + +int32_t kim_handle_reply_init (mach_port_t in_reply_port, + int32_t in_error); + +int32_t kim_handle_reply_enter_identity (mach_port_t in_reply_port, + kim_identity in_identity, + kim_options in_options, + kim_boolean in_change_password, + int32_t in_error); + +int32_t kim_handle_reply_select_identity (mach_port_t in_reply_port, + kim_identity in_identity, + kim_options in_options, + kim_boolean in_change_password, + int32_t in_error); + +int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, + kim_string in_prompt_response, + kim_boolean in_allow_save_response, + int32_t in_error); + +int32_t kim_handle_reply_change_password (mach_port_t in_reply_port, + kim_string in_old_password, + kim_string in_new_password, + kim_string in_vfy_password, + int32_t in_error); + +int32_t kim_handle_reply_handle_error (mach_port_t in_reply_port, + int32_t in_error); + +int32_t kim_handle_reply_fini (mach_port_t in_reply_port, + int32_t in_error); diff --git a/krb5-1-7/src/kim/agent/mac/ServerDemux.m b/krb5-1-7/src/kim/agent/mac/ServerDemux.m new file mode 100644 index 000000000..a2b0e6f8b --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/ServerDemux.m @@ -0,0 +1,668 @@ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "ServerDemux.h" +#import "kim_selection_hints_private.h" +#import "kim_options_private.h" +#import "KerberosAgentListener.h" +#import "KIMUtilities.h" + +// --------------------------------------------------------------------------- + +static kim_boolean caller_is_front_process (pid_t in_pid, + NSString *in_path) +{ + kim_error err = KIM_NO_ERROR; + kim_boolean is_front_process = FALSE; + NSNumber *active_pid = NULL; + + NSBundle *bundle = [NSBundle bundleWithPath: in_path]; + if (bundle) { + NSString *identifier = [bundle bundleIdentifier]; + if (identifier && + ([identifier compare: @"edu.mit.Kerberos.KerberosMenu"] == NSOrderedSame || + [identifier compare: @"com.apple.systemuiserver"] == NSOrderedSame)) { + return TRUE; + } + } + + if (!err) { + NSDictionary *activeApplication = [[NSWorkspace sharedWorkspace] activeApplication]; + if (activeApplication) { + active_pid = [activeApplication objectForKey: @"NSApplicationProcessIdentifier"]; + } + } + + if (!err && active_pid) { + is_front_process = ([active_pid intValue] == in_pid); + } + + return is_front_process; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_init (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + int32_t pid = 0; + char *name = NULL; + char *path = NULL; + bool isFrontProcess = 0; + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &pid); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &name); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &path); + } + + + if (!err) { + isFrontProcess = caller_is_front_process (pid, + [NSString stringWithUTF8String: path]); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener addClientWithPort:in_client_port + replyPort:in_reply_port + name:name + path:path]; + } + + k5_ipc_stream_free_string (name); + k5_ipc_stream_free_string (path); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_init (mach_port_t in_reply_port, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_enter_identity (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + kim_options options = NULL; + + if (!err) { + err = kim_options_create_from_stream (&options, in_request_stream); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener enterIdentityWithClientPort:in_client_port + replyPort:in_reply_port + options:options]; + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_enter_identity (mach_port_t in_reply_port, + kim_identity in_identity, + kim_options in_options, + kim_boolean in_change_password, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + if (!err && !in_error) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, identity_string); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_uint32 (reply, in_change_password); + } + + if (!err && !in_error) { + err = kim_options_write_to_stream (in_options, reply); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + kim_string_free (&identity_string); + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_select_identity (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + kim_selection_hints hints = NULL; + + if (!err) { + err = kim_selection_hints_create_from_stream (&hints, + in_request_stream); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener selectIdentityWithClientPort:in_client_port + replyPort:in_reply_port + hints:hints]; + } + + kim_selection_hints_free (&hints); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_select_identity (mach_port_t in_reply_port, + kim_identity in_identity, + kim_options in_options, + kim_boolean in_change_password, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + if (!err && !in_error) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, identity_string); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_uint32 (reply, in_change_password); + } + + if (!err && !in_error) { + err = kim_options_write_to_stream (in_options, reply); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + kim_string_free (&identity_string); + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *identity_string = NULL; + int32_t type = 0; + int32_t allow_save_reply = 0; + int32_t hide_reply = 0; + char *title = NULL; + char *message = NULL; + char *description = NULL; + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &type); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &allow_save_reply); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &hide_reply); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &title); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &message); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &description); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener promptForAuthWithClientPort:in_client_port + replyPort:in_reply_port + identity:identity_string + promptType:type + allowSave:allow_save_reply + hideReply:hide_reply + title:title + message:message + description:description]; + } + + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_free_string (title); + k5_ipc_stream_free_string (message); + k5_ipc_stream_free_string (description); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, + kim_string in_prompt_response, + kim_boolean in_allow_save_response, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_prompt_response); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_int32 (reply, in_allow_save_response); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_change_password (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *identity_string = NULL; + int32_t old_password_expired = 0; + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, + &old_password_expired); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener changePasswordWithClientPort:in_client_port + replyPort:in_reply_port + identity:identity_string + expired:old_password_expired]; + } + + k5_ipc_stream_free_string (identity_string); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_change_password (mach_port_t in_reply_port, + kim_string in_old_password, + kim_string in_new_password, + kim_string in_vfy_password, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_old_password); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_new_password); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_vfy_password); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_handle_error (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *identity_string = NULL; + int32_t error = 0; + char *message = NULL; + char *description = NULL; + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + /* Can be empty string "" if there is no identity */ + if (!err && !identity_string[0]) { + k5_ipc_stream_free_string (identity_string); + identity_string = NULL; + } + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &error); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &message); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &description); + } + + if (!err) { + // performs selector on main thread + [KerberosAgentListener handleErrorWithClientPort:in_client_port + replyPort:in_reply_port + identity:identity_string + error:error + message:message + description:description]; + } + + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_free_string (message); + k5_ipc_stream_free_string (description); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_handle_error (mach_port_t in_reply_port, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_fini (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + + [KerberosAgentListener removeClientMatchingPort:in_client_port replyPort:in_reply_port]; + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_fini (mach_port_t in_reply_port, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_add_client (mach_port_t in_client_port) +{ + int32_t err = 0; + + if (!err) { + /* Don't need to do anything here since we have an init message */ + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_remove_client (mach_port_t in_client_port) +{ + int32_t err = 0; + + if (!err) { + /* Client exited. Main thread should check for windows belonging to + * in_client_port and close any it finds. */ + [KerberosAgentListener removeClientMatchingPort:in_client_port replyPort:0]; + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_handle_request (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *message_type = NULL; + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &message_type); + } + + if (!err) { + if (!strcmp (message_type, "init")) { + err = kim_handle_request_init (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "enter_identity")) { + err = kim_handle_request_enter_identity (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "select_identity")) { + err = kim_handle_request_select_identity (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "auth_prompt")) { + err = kim_handle_request_auth_prompt (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "change_password")) { + err = kim_handle_request_change_password (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "handle_error")) { + err = kim_handle_request_handle_error (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "fini")) { + err = kim_handle_request_fini (in_client_port, + in_reply_port, + in_request_stream); + + } else { + err = EINVAL; + } + } + + k5_ipc_stream_free_string (message_type); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t kim_agent_listen_loop (void) +{ + return k5_ipc_server_listen_loop (); +} diff --git a/krb5-1-7/src/kim/agent/mac/edu.mit.Kerberos.KerberosAgent.plist b/krb5-1-7/src/kim/agent/mac/edu.mit.Kerberos.KerberosAgent.plist new file mode 100644 index 000000000..5f030ca4c --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/edu.mit.Kerberos.KerberosAgent.plist @@ -0,0 +1,28 @@ + + + + + Label + edu.mit.Kerberos.KerberosAgent + Program + /System/Library/CoreServices/KerberosAgent.app/Contents/MacOS/KerberosAgent + MachServices + + edu.mit.Kerberos.KerberosAgent.ipcLookup + + HideUntilCheckIn + + ResetAtClose + + + edu.mit.Kerberos.KerberosAgent.ipcService + + + EnableTransactions + + ThrottleInterval + 1 + OnDemand + + + diff --git a/krb5-1-7/src/kim/agent/mac/main.m b/krb5-1-7/src/kim/agent/mac/main.m new file mode 100644 index 000000000..1e887a003 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/main.m @@ -0,0 +1,6 @@ +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/krb5-1-7/src/kim/agent/mac/resources/Add.tiff b/krb5-1-7/src/kim/agent/mac/resources/Add.tiff new file mode 100644 index 0000000000000000000000000000000000000000..b78b0c2a631a0fd47323d347943cf1f44180a630 GIT binary patch literal 728 zcmebEWzb?^U=nIzP;kr;V9;i5KCsXr!^KRLug&>Upu`eAU4iZ+4-->lO8?bNus^@a zQe=`_?W9xum$v^|^H+D8_cEcMQ?4cJOx}O~^Uf=u%IfD`Q2!$SrZR`KFYMEt`Yu(O$@V{e!^7dY_mg)QJ-=D0$tM+Ej|2x9puF2f~d-Ht# z?y6Y1`JT70y#Bgd#SCi-v|3oe|W$9gYj+70~17qUhm^wBhK!);f~GAJ?BmA z`3?qZuX{H4qUV2+xff$X#au7uBuXCrxF%KF&G1a7^zn&T3ZBgq;{2~LPe`U!$>WmF zMAZ|Ya;B<#8uiRnKQ(E}f@kxLPX5=KXLM()p7*6U2Mteu);VhIW9)O%`0V763(w{S zcmB7S7d+>wmEYwxA8pTle)HAd--PF<{e>x_4A173c>Z^pR}w4g7I-CB(evV$wW{7h zCTBIhFHgB@@azijTBl7{vZwk6T@@A1S}c(HH#Yp5Xm4udwW(`!Bd>OFFfi~jGB7YR zFfcGOhyw{mC|eB3W&*QWfa&D`BQsQ-6)4UIWitWUf($@;pk4+B4n|R^I8cO93?|N) z!YB@7GjTFXF#t^fsb@ODC=F*{V3dLC1V!kV1Is- zrN|_=+DWJQFKz#`=CAHF?`1+ir(8?cnY{n}=bcwRmDSI?p#DYtPbu4f?@RHoex>To z_6fhd%9Lwr*vjzb*Ro1iZ7tduy&*_5WXj&M!||J=a>aIi-F7}^Q^cBWr)#fW&D(u< z-PGvbW8drdB*Seki;D5*dz(kQ$@kw^SnuXjPhS80WmVOj`|i|c=b!wY#W8>KiBAp}dc>Yhxv=s-*OUu;ba|Wu&RFsvF66Nl zbl#}rD0o!R#N*ji!OZ_+Qw3{cCENmgGNq3dp2?MU+xVtX_JrVq@^=zt9=YNfGd0kqwQTNoRH(T|+jd^zJpP4Lj;Mvq*&;KS zXnFSYny1!&#%EqypPzi?!?O##Yne7($ezmUbWub&Yq3D)Us?A{BE71fm!_=M^}N`@ z!N9=B$iTqN0E}z~aUj76Ws3pXOkg$(0|V0xMrNouD^Q#b%4Pzx1sQ + + + 1050 + 9F33 + 672 + 949.34 + 352.00 + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + AuthenticationController + + + FirstResponder + + + NSApplication + + + + YES + username + realm + old_password + new_password + verify_password + title + message + description + allow_save_password + realm_history + should_save_password + isPrincipalValid + prompt_response + isPromptValid + isChangePasswordValid + save_response + allow_save + forwardable + addressless + renewable + valid_lifetime + renewal_lifetime + min_renewal_lifetime + max_renewal_lifetime + max_valid_lifetime + min_valid_lifetime + identity_string + favorite_identity_strings + isBusy + acceptingInput + + YES + + + + + YES + maxValidLifetime + minValidLifetime + validLifetime + valid_lifetime + minRenewableLifetime + maxRenewableLifetime + renewa + renewal_lifetime + usesDefaultTicketOptions + + YES + + + + + 274 + + YES + + + 266 + {{101, 103}, {382, 54}} + + YES + + 67239424 + 272629760 + Please enter your Kerberos identity + + LucidaGrande + 1.300000e+01 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 290 + {{104, 59}, {379, 26}} + + YES + + 343014976 + 272630784 + + + + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 5 + YES + YES + + + + 274 + {15, 0} + + + YES + + YES + + + 1.200000e+01 + 1.000000e+01 + 1.000000e+03 + + 75628032 + 0 + + + LucidaGrande + 1.200000e+01 + 16 + + + 3 + MC4zMzMzMzI5OQA + + + + + 338820672 + 1024 + + + YES + + 6 + System + controlBackgroundColor + + + + + 3 + YES + + + + 3.000000e+00 + 2.000000e+00 + + + 6 + System + gridColor + + 3 + MC41AA + + + 1.900000e+01 + tableViewAction: + -767524864 + + + + 1 + 15 + 0 + YES + + + + + + 292 + {{17, 64}, {82, 17}} + + YES + + 67239424 + 71303168 + Identity: + + + + + + + + + 289 + {{388, 15}, {98, 32}} + + YES + + 67239424 + 134217728 + Continue + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 289 + {{295, 15}, {93, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 268 + {{20, 103}, {64, 64}} + + BadgedImageView + + + + 292 + {{20, 20}, {38, 26}} + + YES + + -2076049856 + 134219776 + + + -2030944001 + 34 + + + 400 + 75 + + + YES + + + 2147483647 + 1 + + NSImage + NSActionTemplate + + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + VGlja2V0IE9wdGlvbnPigKY + + 2147483647 + + + _popUpItemAction: + + + + + Q2hhbmdlIFBhc3N3b3Jk4oCmA + + 2147483647 + + + _popUpItemAction: + + + + + YES + 1 + YES + YES + 2 + + + + + 1292 + + {{66, 25}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {500, 187} + NSView + + + + 274 + + YES + + + 266 + {{104, 82}, {376, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + + 6 + System + textColor + + + + + + + 289 + {{388, 12}, {98, 32}} + + YES + + 67239424 + 134217728 + Continue + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 289 + {{295, 12}, {93, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 266 + {{101, 124}, {382, 54}} + + YES + + 67239424 + 272629760 + Please enter the Kerberos password for %@ + + + + + + + + + 268 + {{17, 84}, {80, 17}} + + YES + + 68288064 + 71304192 + Password: + + + + + + + + + 290 + {{102, 58}, {380, 18}} + + YES + + -2080244224 + 0 + Remember this password in my keychain + + + 1211912703 + 130 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{20, 124}, {64, 64}} + + BadgedImageView + + + + 1292 + + {{19, 22}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {500, 208} + NSView + + + + 274 + + YES + + + 266 + {{101, 140}, {382, 17}} + + YES + + 67239424 + 272629760 + %@ + + + + + + + + + 290 + {{202, 62}, {278, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + + + + + + 289 + {{388, 12}, {98, 32}} + + YES + + 67239424 + 134217728 + Continue + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 274 + {{101, 104}, {382, 28}} + + YES + + 67239424 + 272629760 + b25lIGxpbmUKdHdvIGxpbmVzA + + LucidaGrande + 1.100000e+01 + 3100 + + + + + + + + + 268 + {{20, 103}, {64, 64}} + + BadgedImageView + + + + 289 + {{295, 12}, {93, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 292 + {{17, 20}, {180, 61}} + + YES + + 67239424 + 71303168 + I am a really big prompt label: + + LucidaGrande + 1.300000e+01 + 16 + + + + + + + + + 1292 + + {{20, 22}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {500, 187} + NSView + + + + 286 + + YES + + + 268 + {{20, 146}, {64, 64}} + + BadgedImageView + + + + 266 + {{101, 146}, {382, 54}} + + YES + + 67239424 + 272629760 + Kerberos Authentication Failed. + + + + + + + + + 290 + {{161, 116}, {319, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + + + + + + 292 + {{62, 118}, {94, 17}} + + YES + + 68288064 + 71304192 + Old Password: + + + + + + + + + 292 + {{57, 90}, {99, 17}} + + YES + + 68288064 + 71304192 + New Password: + + + + + + + + + 292 + {{17, 62}, {139, 17}} + + YES + + 68288064 + 71304192 + Verify New Password: + + + + + + + + + 290 + {{161, 88}, {319, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + + + + + + 290 + {{161, 60}, {319, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + + + + + + 289 + {{388, 12}, {98, 32}} + + YES + + 67239424 + 134217728 + Continue + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 289 + {{295, 12}, {93, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 1292 + + {{20, 22}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {500, 230} + NSView + + + + 274 + + YES + + + 268 + {{20, 126}, {64, 64}} + + BadgedImageView + + + + 266 + {{101, 149}, {382, 17}} + + YES + + 67239424 + 272629760 + Kerberos Authentication Failed. + + + + + + + + + 274 + {{101, 65}, {382, 76}} + + YES + + 67239424 + 272760832 + Password incorrect + + + + 3 + MSAwLjk3MDAwMDAzAA + + + + + + + 289 + {{404, 12}, {82, 32}} + + YES + + 67239424 + 134217728 + OK + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + {500, 210} + NSView + + + 5 + 2 + {{378, 236}, {500, 210}} + 1886912512 + Authenticate to Kerberos + + NSWindow + + + View + + {600, 400} + {484, 199} + + + 256 + {500, 210} + + + {{0, 0}, {1920, 1178}} + {484, 221} + {600, 422} + + + + 1 + 2 + {{21, 28}, {430, 305}} + 1886912512 + Kerberos Ticket Options + NSWindow + + View + + {3.40282e+38, 3.40282e+38} + {430, 283} + + + 256 + + YES + + + 266 + {{38, 214}, {374, 25}} + + YES + + 67501824 + 0 + + + + + Helvetica + 1.200000e+01 + 16 + + + 1.000000e+02 + 0.000000e+00 + 0.000000e+00 + 0.000000e+00 + 11 + 0 + NO + NO + + + + + 268 + {{17, 246}, {396, 17}} + + YES + + 67239424 + 4194304 + Get tickets that are valid for: + + + + + + + + + 266 + {{37, 192}, {376, 14}} + + YES + + 67239424 + 4325376 + 10 hours + + + + + + + + + 266 + {{37, 82}, {375, 25}} + + YES + + 67501824 + 0 + + + + + + 1.000000e+05 + 0.000000e+00 + 0.000000e+00 + 0.000000e+00 + 11 + 0 + NO + NO + + + + + 268 + {{18, 134}, {394, 18}} + + YES + + 67239424 + 0 + Get tickets without IP addresses (NAT mode) + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{18, 156}, {394, 18}} + + YES + + 67239424 + 0 + Get tickets that can be forwarded to other computers + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{18, 112}, {394, 18}} + + YES + + 67239424 + 0 + Get tickets that can be renewed for: + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 266 + {{36, 60}, {377, 14}} + + YES + + 67239424 + 4325376 + 7 days + + + + + + + + + 256 + {{334, 12}, {82, 32}} + + YES + + 67239424 + 134217728 + OK + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 256 + {{252, 12}, {82, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 268 + {{18, 269}, {184, 18}} + + YES + + -2080244224 + 0 + Use default ticket options + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {430, 305} + + {{0, 0}, {1440, 878}} + {430, 305} + {3.40282e+38, 3.40282e+38} + + + KerberosTimeFormatter + + + + + YES + + + identityView + + + + 300295 + + + + passwordView + + + + 300296 + + + + samView + + + + 300297 + + + + expiredPasswordView + + + + 300298 + + + + value: selection.message + + + + + + value: selection.message + value + selection.message + 2 + + + 300301 + + + + value: selection.message + + + + + + value: selection.message + value + selection.message + 2 + + + 300303 + + + + value: selection.description + + + + + + value: selection.description + value + selection.description + 2 + + + 300304 + + + + glueController + + + + 300326 + + + + window + + + + 300339 + + + + value: selection.message + + + + + + value: selection.message + value + selection.message + 2 + + + 300344 + + + + enterIdentity: + + + + 300347 + + + + cancel: + + + + 300348 + + + + enabled: selection.isPrincipalValid + + + + + + enabled: selection.isPrincipalValid + enabled + selection.isPrincipalValid + 2 + + + 300351 + + + + enterBadge + + + + 300353 + + + + passwordField + + + + 300354 + + + + cancel: + + + + 300359 + + + + passwordBadge + + + + 300360 + + + + answerAuthPrompt: + + + + 300361 + + + + rememberPasswordInKeychainCheckBox + + + + 300364 + + + + enabled: selection.isPromptValid + + + + + + enabled: selection.isPromptValid + enabled + selection.isPromptValid + 2 + + + 300365 + + + + value: selection.prompt_response + + + + + + value: selection.prompt_response + value + selection.prompt_response + + NSContinuouslyUpdatesValue + + + 2 + + + 300368 + + + + samBadge + + + + 300369 + + + + samPromptField + + + + 300370 + + + + answerAuthPrompt: + + + + 300371 + + + + cancel: + + + + 300372 + + + + value: selection.prompt_response + + + + + + value: selection.prompt_response + value + selection.prompt_response + + NSContinuouslyUpdatesValue + + + 2 + + + 300377 + + + + enabled: selection.isPromptValid + + + + + + enabled: selection.isPromptValid + enabled + selection.isPromptValid + 2 + + + 300378 + + + + errorView + + + + 300379 + + + + errorBadge + + + + 300380 + + + + showedError: + + + + 300381 + + + + changePasswordView + + + + 300382 + + + + changePasswordBadge + + + + 300383 + + + + changePassword: + + + + 300403 + + + + cancel: + + + + 300404 + + + + value: selection.message + + + + + + value: selection.message + value + selection.message + 2 + + + 300405 + + + + oldPasswordField + + + + 300407 + + + + nextKeyView + + + + 300408 + + + + nextKeyView + + + + 300409 + + + + nextKeyView + + + + 300410 + + + + enabled: selection.isChangePasswordValid + + + + + + enabled: selection.isChangePasswordValid + enabled + selection.isChangePasswordValid + 2 + + + 300411 + + + + value: selection.old_password + + + + + + value: selection.old_password + value + selection.old_password + + NSContinuouslyUpdatesValue + + + 2 + + + 300412 + + + + value: selection.new_password + + + + + + value: selection.new_password + value + selection.new_password + + NSContinuouslyUpdatesValue + + + 2 + + + 300413 + + + + value: selection.verify_password + + + + + + value: selection.verify_password + value + selection.verify_password + + NSContinuouslyUpdatesValue + + + 2 + + + 300414 + + + + containerView + + + + 300415 + + + + value: selection.save_response + + + + + + value: selection.save_response + value + selection.save_response + 2 + + + 300416 + + + + ticketOptionsSheet + + + + 300468 + + + + ticketOptionsController + + + + 300470 + + + + maxValue: selection.maxValidLifetime + + + + + + maxValue: selection.maxValidLifetime + maxValue + selection.maxValidLifetime + 2 + + + 300472 + + + + minValue: selection.minValidLifetime + + + + + + minValue: selection.minValidLifetime + minValue + selection.minValidLifetime + + 2 + + + 300478 + + + + value: selection.forwardable + + + + + + value: selection.forwardable + value + selection.forwardable + 2 + + + 300481 + + + + value: selection.addressless + + + + + + value: selection.addressless + value + selection.addressless + 2 + + + 300482 + + + + value: selection.renewable + + + + + + value: selection.renewable + value + selection.renewable + 2 + + + 300483 + + + + maxValue: selection.maxRenewableLifetime + + + + + + maxValue: selection.maxRenewableLifetime + maxValue + selection.maxRenewableLifetime + 2 + + + 300494 + + + + minValue: selection.minRenewableLifetime + + + + + + minValue: selection.minRenewableLifetime + minValue + selection.minRenewableLifetime + + 2 + + + 300495 + + + + enabled: selection.renewable + + + + + + enabled: selection.renewable + enabled + selection.renewable + 2 + + + 300497 + + + + showTicketOptions: + + + + 300503 + + + + saveTicketOptions: + + + + 300504 + + + + cancelTicketOptions: + + + + 300505 + + + + validLifetimeSlider + + + + 300506 + + + + renewableLifetimeSlider + + + + 300507 + + + + sliderDidChange: + + + + 300508 + + + + sliderDidChange: + + + + 300509 + + + + formatter + + + + 300511 + + + + identityField + + + + 300513 + + + + contentValues: selection.favorite_identity_strings + + + + + + contentValues: selection.favorite_identity_strings + contentValues + selection.favorite_identity_strings + 2 + + + 300515 + + + + value: selection.identity_string + + + + + + value: selection.identity_string + value + selection.identity_string + + NSContinuouslyUpdatesValue + + + + 2 + + + 300516 + + + + value: selection.valid_lifetime + + + + + + value: selection.valid_lifetime + value + selection.valid_lifetime + + NSContinuouslyUpdatesValue + + + 2 + + + 300517 + + + + value: selection.renewal_lifetime + + + + + + value: selection.renewal_lifetime + value + selection.renewal_lifetime + + NSContinuouslyUpdatesValue + + + 2 + + + 300518 + + + + lifetimeFormatter + + + + 300519 + + + + formatter + + + + 300520 + + + + changePasswordGearAction: + + + + 300522 + + + + value: selection.message + + + + + + value: selection.message + value + selection.message + 2 + + + 300524 + + + + value: selection.title + + + + + + value: selection.title + value + selection.title + 2 + + + 300525 + + + + displayPatternValue1: selection.description + + + + + + displayPatternValue1: selection.description + displayPatternValue1 + selection.description + + NSDisplayPattern + %{value1}@: + + 2 + + + 300529 + + + + samSpinny + + + + 300532 + + + + changePasswordSpinny + + + + 300537 + + + + enterSpinny + + + + 300538 + + + + passwordSpinny + + + + 300539 + + + + enabled: selection.isPrincipalValid + + + + + + enabled: selection.isPrincipalValid + enabled + selection.isPrincipalValid + 2 + + + 300540 + + + + value: selection.usesDefaultTicketOptions + + + + + + value: selection.usesDefaultTicketOptions + value + selection.usesDefaultTicketOptions + 2 + + + 300545 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300547 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300549 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300551 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300553 + + + + enabled2: selection.usesDefaultTicketOptions + + + + + + enabled2: selection.usesDefaultTicketOptions + enabled2 + selection.usesDefaultTicketOptions + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + NSValueTransformerName + + + YES + + + + + NSNegateBoolean + + + + 2 + + + 300555 + + + + checkboxDidChange: + + + + 300556 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300560 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300561 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300562 + + + + enabled2: selection.acceptingInput + + + + + + enabled2: selection.acceptingInput + enabled2 + selection.acceptingInput + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + + + YES + + + + + + + + 2 + + + 300563 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300564 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300565 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300566 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300567 + + + + enabled2: selection.acceptingInput + + + + + + enabled2: selection.acceptingInput + enabled2 + selection.acceptingInput + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + + + YES + + + + + + + + 2 + + + 300568 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300569 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300570 + + + + enabled2: selection.acceptingInput + + + + + + enabled2: selection.acceptingInput + enabled2 + selection.acceptingInput + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + + + YES + + + + + + + + 2 + + + 300571 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300572 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300573 + + + + enabled: selection.acceptingInput + + + + + + enabled: selection.acceptingInput + enabled + selection.acceptingInput + 2 + + + 300574 + + + + enabled2: selection.acceptingInput + + + + + + enabled2: selection.acceptingInput + enabled2 + selection.acceptingInput + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + + + YES + + + + + + + + 2 + + + 300575 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + 19 + + + YES + + + + Authenticate to Kerberos + + + 20 + + + YES + + + + + -3 + + + Application + + + 300157 + + + YES + + + + + + + + + + + Enter Identity + + + 300221 + + + YES + + + + + + 300163 + + + YES + + + + + + 300162 + + + YES + + + + + + 300165 + + + + + 300161 + + + YES + + + + + + 300158 + + + YES + + + + + + 300172 + + + + + 300169 + + + + + 300168 + + + + + 300167 + + + + + 300222 + + + + + 300175 + + + YES + + + + + + + + + + + Enter Password + + + 300179 + + + YES + + + + + + 300192 + + + + + 300182 + + + YES + + + + + + 300178 + + + YES + + + + + + 300183 + + + YES + + + + + + 300180 + + + YES + + + + + + 300177 + + + YES + + + + + + 300190 + + + + + 300187 + + + + + 300184 + + + + + 300189 + + + + + 300185 + + + + + 300188 + + + + + 300193 + + + YES + + + + + + + + + + + SAM Authentication + + + 300210 + + + + + 300201 + + + YES + + + + + + 300195 + + + YES + + + + + + 300196 + + + YES + + + + + + 300223 + + + YES + + + + + + 300197 + + + YES + + + + + + 300206 + + + + + 300224 + + + + + 300207 + + + + + 300208 + + + + + 300202 + + + + + 300274 + + + YES + + + + + + + + + + + + + + Change Password + + + 300275 + + + + + 300288 + + + YES + + + + + + 300289 + + + + + 300211 + + + YES + + + + + + + Result + + + 300215 + + + YES + + + + + + 300212 + + + + + 300217 + + + YES + + + + + + 300213 + + + YES + + + + + + 300214 + + + + + 300218 + + + + + 300216 + + + + + 300300 + + + Glue Controller + + + 300312 + + + YES + + + + + + 300313 + + + YES + + + + + + 300314 + + + YES + + + + + + + + 300316 + + + + + 300384 + + + YES + + + + + + 300385 + + + YES + + + + + + 300386 + + + + + 300387 + + + + + 300388 + + + YES + + + + + + 300389 + + + + + 300390 + + + YES + + + + + + 300391 + + + + + 300392 + + + YES + + + + + + 300393 + + + + + 300394 + + + YES + + + + + + 300395 + + + + + 300396 + + + YES + + + + + + 300397 + + + YES + + + + + + 300398 + + + + + 300399 + + + + + 300419 + + + YES + + + + Options + + + 300420 + + + YES + + + + + + + + + + + + + + + + 300421 + + + YES + + + + + + 300422 + + + YES + + + + + + 300423 + + + YES + + + + + + 300424 + + + YES + + + + + + 300425 + + + YES + + + + + + 300426 + + + YES + + + + + + 300427 + + + YES + + + + + + 300428 + + + YES + + + + + + 300429 + + + YES + + + + + + 300430 + + + YES + + + + + + 300431 + + + + + 300432 + + + + + 300433 + + + + + 300434 + + + + + 300435 + + + + + 300436 + + + + + 300437 + + + + + 300438 + + + + + 300439 + + + + + 300440 + + + + + 300464 + + + + + 300469 + + + Ticket Options Controller + + + 300502 + + + + + 300510 + + + + + 300526 + + + YES + + + + + + 300527 + + + + + 300530 + + + + + 300533 + + + + + 300534 + + + + + 300536 + + + + + 300543 + + + YES + + + + + + 300544 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + 19.IBEditorWindowLastContentRect + 19.IBPluginDependency + 19.IBWindowTemplateEditedContentRect + 19.ImportedFromIB2 + 19.NSWindowTemplate.visibleAtLaunch + 19.editorWindowContentRectSynchronizationRect + 19.windowTemplate.hasMaxSize + 19.windowTemplate.hasMinSize + 19.windowTemplate.maxSize + 19.windowTemplate.minSize + 20.IBPluginDependency + 20.ImportedFromIB2 + 300157.IBEditorWindowLastContentRect + 300157.IBPluginDependency + 300158.IBPluginDependency + 300158.ImportedFromIB2 + 300161.IBPluginDependency + 300161.ImportedFromIB2 + 300162.IBPluginDependency + 300162.ImportedFromIB2 + 300163.IBPluginDependency + 300163.ImportedFromIB2 + 300165.IBPluginDependency + 300175.IBEditorWindowLastContentRect + 300175.IBPluginDependency + 300177.CustomClassName + 300177.IBPluginDependency + 300177.ImportedFromIB2 + 300178.IBPluginDependency + 300178.ImportedFromIB2 + 300179.IBPluginDependency + 300179.ImportedFromIB2 + 300180.IBPluginDependency + 300180.ImportedFromIB2 + 300182.IBPluginDependency + 300183.IBPluginDependency + 300184.IBPluginDependency + 300185.IBPluginDependency + 300192.IBPluginDependency + 300193.IBEditorWindowLastContentRect + 300193.IBPluginDependency + 300195.IBPluginDependency + 300195.ImportedFromIB2 + 300196.CustomClassName + 300196.IBPluginDependency + 300196.ImportedFromIB2 + 300197.IBPluginDependency + 300197.ImportedFromIB2 + 300201.IBPluginDependency + 300201.ImportedFromIB2 + 300210.IBPluginDependency + 300211.IBEditorWindowLastContentRect + 300211.IBPluginDependency + 300212.IBPluginDependency + 300213.IBPluginDependency + 300213.ImportedFromIB2 + 300215.IBPluginDependency + 300215.ImportedFromIB2 + 300217.IBPluginDependency + 300217.ImportedFromIB2 + 300221.IBPluginDependency + 300221.ImportedFromIB2 + 300223.IBPluginDependency + 300223.ImportedFromIB2 + 300274.IBEditorWindowLastContentRect + 300274.IBPluginDependency + 300275.IBPluginDependency + 300288.IBPluginDependency + 300288.ImportedFromIB2 + 300300.IBPluginDependency + 300312.IBPluginDependency + 300313.IBPluginDependency + 300314.IBEditorWindowLastContentRect + 300314.IBPluginDependency + 300316.IBPluginDependency + 300384.CustomClassName + 300384.IBPluginDependency + 300384.ImportedFromIB2 + 300385.IBPluginDependency + 300386.IBPluginDependency + 300388.IBPluginDependency + 300389.IBPluginDependency + 300390.IBPluginDependency + 300391.IBPluginDependency + 300392.CustomClassName + 300392.IBPluginDependency + 300392.ImportedFromIB2 + 300394.CustomClassName + 300394.IBPluginDependency + 300394.ImportedFromIB2 + 300396.IBPluginDependency + 300396.ImportedFromIB2 + 300397.IBPluginDependency + 300397.ImportedFromIB2 + 300419.IBEditorWindowLastContentRect + 300419.IBPluginDependency + 300419.IBWindowTemplateEditedContentRect + 300419.ImportedFromIB2 + 300419.windowTemplate.hasMaxSize + 300419.windowTemplate.hasMinSize + 300419.windowTemplate.maxSize + 300419.windowTemplate.minSize + 300420.IBPluginDependency + 300420.ImportedFromIB2 + 300421.IBPluginDependency + 300421.ImportedFromIB2 + 300422.IBPluginDependency + 300422.ImportedFromIB2 + 300423.IBPluginDependency + 300423.ImportedFromIB2 + 300424.IBPluginDependency + 300424.ImportedFromIB2 + 300425.IBPluginDependency + 300425.ImportedFromIB2 + 300426.IBPluginDependency + 300426.ImportedFromIB2 + 300427.IBPluginDependency + 300427.ImportedFromIB2 + 300428.IBPluginDependency + 300428.ImportedFromIB2 + 300429.IBPluginDependency + 300429.ImportedFromIB2 + 300430.IBPluginDependency + 300430.ImportedFromIB2 + 300464.IBPluginDependency + 300469.IBPluginDependency + 300502.IBPluginDependency + 300510.IBPluginDependency + 300526.IBPluginDependency + 300527.IBPluginDependency + 300530.IBPluginDependency + 300533.IBPluginDependency + 300534.IBPluginDependency + 300536.IBPluginDependency + 300543.IBPluginDependency + 300544.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{628, 646}, {500, 210}} + com.apple.InterfaceBuilder.CocoaPlugin + {{628, 646}, {500, 210}} + + + {{932, 664}, {484, 199}} + + + {600, 400} + {484, 199} + com.apple.InterfaceBuilder.CocoaPlugin + + {{338, 521}, {500, 187}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{628, 239}, {500, 208}} + com.apple.InterfaceBuilder.CocoaPlugin + NSSecureTextField + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{597, 343}, {500, 187}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + NSSecureTextField + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{553, 638}, {500, 210}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{427, 495}, {500, 230}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{347, 504}, {189, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + NSSecureTextField + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + NSSecureTextField + com.apple.InterfaceBuilder.CocoaPlugin + + NSSecureTextField + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{647, 390}, {430, 305}} + com.apple.InterfaceBuilder.CocoaPlugin + {{647, 390}, {430, 305}} + + + + {3.40282e+38, 3.40282e+38} + {430, 283} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 300575 + + + + YES + + AuthenticationController + NSWindowController + + YES + + YES + answerAuthPrompt: + cancel: + cancelTicketOptions: + changePassword: + changePasswordGearAction: + checkboxDidChange: + enterIdentity: + saveTicketOptions: + showTicketOptions: + showedError: + sliderDidChange: + + + YES + id + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + changePasswordBadge + changePasswordSpinny + changePasswordView + containerView + enterBadge + enterSpinny + errorBadge + errorView + expiredPasswordView + glueController + identityField + identityView + lifetimeFormatter + oldPasswordField + passwordBadge + passwordField + passwordSpinny + passwordView + rememberPasswordInKeychainCheckBox + renewableLifetimeSlider + samBadge + samPromptField + samSpinny + samView + ticketOptionsController + ticketOptionsSheet + validLifetimeSlider + + + YES + BadgedImageView + NSProgressIndicator + NSView + NSView + BadgedImageView + NSProgressIndicator + BadgedImageView + NSView + NSView + NSObjectController + NSTextField + NSView + KerberosTimeFormatter + NSTextField + BadgedImageView + NSTextField + NSProgressIndicator + NSView + NSButton + NSSlider + BadgedImageView + NSTextField + NSProgressIndicator + NSView + NSObjectController + NSWindow + NSSlider + + + + IBProjectSource + ../Sources/kim/agent/mac/AuthenticationController.h + + + + BadgedImageView + NSView + + IBProjectSource + ../Sources/kim/agent/mac/BadgedImageView.h + + + + FirstResponder + NSObject + + IBUserSource + + + + + KerberosTimeFormatter + NSFormatter + + IBProjectSource + ../Sources/kim/agent/mac/KerberosFormatters.h + + + + + 0 + ../../../../../../Projects/Kerberos5.xcodeproj + 3 + + diff --git a/krb5-1-7/src/kim/agent/mac/resources/English.lproj/AuthenticationController.strings b/krb5-1-7/src/kim/agent/mac/resources/English.lproj/AuthenticationController.strings new file mode 100644 index 0000000000000000000000000000000000000000..bcc575632fec4d55f0244140192e1bd522b69df9 GIT binary patch literal 2000 zcmcgt;Y!0W5dMDq6rtch-#|pi5Cnf%)ECgLYOt&`ZPC8G`dzY&B@11tb%ZvTOLBK# za`)x?2N`B)(clepR9I0m>`S(S(hO_15*iCUaZcMcIcGH2F8E(lU*evtKWL{w%~cr` zF8F0Q#T9$AnblURsS$r-Pobm5)@nN1Dz+L!>6T-IXZx>cS<&B;BZ*S;>*(PeC!;Xz zN33W+Z2yBnPON78ByvMM<1yrsr4**)U{H9mXq3Hihv?9~49TMKKK#gG%59FySxVNp ztdM;1IW=7drOwsI(%=6j(lL25BqP!hPZ{Z$Y`EFf_8nQk^Gwa!NJqP?b&>o13bBR5 z4DmoVs#uTl&Rs8Q+4=VS)4rt+=9cePcx9f(cNCAW@x?Q6Tq*33_AFZG{gJk%0^)oL zZ$a4zghPwK{uwpGL@ldnN!jzUaQ?fs+i+Hq>xHo$0^#8Xms{rQLzjL*hE$Y8H~a+& ZBa|0LPG$cM=|3mW#(kKkWv&V1{sqD}OGf|z literal 0 HcmV?d00001 diff --git a/krb5-1-7/src/kim/agent/mac/resources/English.lproj/MainMenu.xib b/krb5-1-7/src/kim/agent/mac/resources/English.lproj/MainMenu.xib new file mode 100644 index 000000000..f56ab6337 --- /dev/null +++ b/krb5-1-7/src/kim/agent/mac/resources/English.lproj/MainMenu.xib @@ -0,0 +1,791 @@ + + + + 1050 + 9F33 + 672 + 949.34 + 352.00 + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + + NSApplication + + + + FirstResponder + + + NSApplication + + + MainMenu + + YES + + + KerberosAgent + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + KerberosAgent + + YES + + + About KerberosAgent + + 2147483647 + + + + + _NSAppleMenu + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + YES + + + Close + w + 1048576 + 2147483647 + + + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + + Help + + + YES + + + KerberosAgent Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + KerberosAgentController + + + + + YES + + + arrangeInFront: + + + + 39 + + + + showHelp: + + + + 122 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + cut: + + + + 175 + + + + paste: + + + + 176 + + + + redo: + + + + 178 + + + + selectAll: + + + + 179 + + + + undo: + + + + 180 + + + + copy: + + + + 181 + + + + delete: + + + + 201 + + + + performZoom: + + + + 204 + + + + pasteAsPlainText: + + + + 211 + + + + performMiniaturize: + + + + 235 + + + + performClose: + + + + 246 + + + + delegate + + + + 300448 + + + + delegate + + + + 300468 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + 29 + + + YES + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 24 + + + YES + + + + + + + + + + 5 + + + + + 23 + + + + + 203 + + + + + 233 + + + + + 234 + + + + + 56 + + + YES + + + + + + 57 + + + YES + + + + + + 58 + + + + + 103 + + + YES + + + + + + 106 + + + YES + + + + + + 111 + + + + + 163 + + + YES + + + + + + 169 + + + YES + + + + + + + + + + + + + + 156 + + + + + 157 + + + + + 158 + + + + + 160 + + + + + 164 + + + + + 171 + + + + + 172 + + + + + 173 + + + + + 210 + + + + + -3 + + + Application + + + 300447 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 156.IBPluginDependency + 156.ImportedFromIB2 + 157.IBPluginDependency + 157.ImportedFromIB2 + 158.IBPluginDependency + 158.ImportedFromIB2 + 160.IBPluginDependency + 160.ImportedFromIB2 + 163.IBPluginDependency + 163.ImportedFromIB2 + 164.IBPluginDependency + 164.ImportedFromIB2 + 169.IBEditorWindowLastContentRect + 169.IBPluginDependency + 169.ImportedFromIB2 + 169.editorWindowContentRectSynchronizationRect + 171.IBPluginDependency + 171.ImportedFromIB2 + 172.IBPluginDependency + 172.ImportedFromIB2 + 173.IBPluginDependency + 173.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 233.IBPluginDependency + 233.ImportedFromIB2 + 234.IBPluginDependency + 234.ImportedFromIB2 + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.editorWindowContentRectSynchronizationRect + 300447.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{1137, 580}, {211, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{630, 563}, {253, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{1022, 430}, {253, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{1066, 510}, {197, 93}} + {{492, 736}, {314, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{884, 603}, {314, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{504, 713}, {202, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{896, 420}, {240, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 300484 + + + + YES + + FirstResponder + NSObject + + IBUserSource + + + + + KerberosAgentController + NSObject + + fakeANewClient: + id + + + IBProjectSource + ../Sources/kim/agent/mac/KerberosAgentController.h + + + + + 0 + ../../../../../../Projects/Kerberos5.xcodeproj + 3 + + diff --git a/krb5-1-7/src/kim/agent/mac/resources/English.lproj/SelectIdentity.strings b/krb5-1-7/src/kim/agent/mac/resources/English.lproj/SelectIdentity.strings new file mode 100644 index 0000000000000000000000000000000000000000..db20365e908f59a9ed472839a5f801f9b49b81f0 GIT binary patch literal 538 zcmbu6O$x#=5QX2`Qw#x5A%gA{7m7VWt%8MOw5^DjSHGq$QY&^LVUo%Gda_$;F1oT8#GFi1%xSC{XWnGf;1xtl9YeSAqNmU3 zdt(|o(~3y0UD!Q&1GCG;X`&G*zxei<887u$&36;#jsu&2I1RB{G_$PHvQoCvun4+! cnboY?YSU-^@ca= + + + 1050 + 9F33 + 672 + 949.34 + 352.00 + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + SelectIdentityController + + + FirstResponder + + + NSApplication + + + 13 + 2 + {{516, 414}, {500, 273}} + 1886913536 + Select a Kerberos Identity + + NSWindow + + + View + + {800, 800} + {400, 273} + + + 256 + + YES + + + 266 + {{101, 226}, {382, 17}} + + YES + + 67239424 + 272629760 + %@ requires you select a Kerberos identity + + LucidaGrande + 1.300000e+01 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 266 + {{101, 181}, {382, 37}} + + YES + + 67239424 + 272629760 + %@ + + LucidaGrande + 1.100000e+01 + 3100 + + + + + + + + + 289 + {{399, 13}, {87, 32}} + + YES + + 67239424 + 134217728 + Select + + + -2038284033 + 1 + + + DQ + 200 + 25 + + + + + 289 + {{317, 13}, {82, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 1 + + + Gw + 200 + 25 + + + + + 268 + {{20, 189}, {64, 64}} + + BadgedImageView + + + + 292 + {{20, 19}, {28, 24}} + + YES + + -2080244224 + 134217728 + + + + -2030812929 + 162 + + NSImage + NSAddTemplate + + + + 400 + 75 + + + + + 274 + + YES + + + 2304 + + YES + + + 256 + {458, 95} + + YES + + + 256 + {458, 17} + + + + + + -2147483392 + {{-26, 0}, {16, 17}} + + + + YES + + identityColumn + 3.260000e+02 + 4.000000e+01 + 1.000000e+03 + + 75628032 + 0 + Identity + + + 3 + MC4zMzMzMzI5OQA + + + 6 + System + headerTextColor + + + + + 337772096 + 2048 + Text Cell + + LucidaGrande + 1.100000e+01 + 16 + + + + 6 + System + controlBackgroundColor + + + + + 3 + YES + + + + timeRemainingColumn + 1.000000e+02 + 1.000000e+02 + 2.000000e+02 + + 75628032 + 67108864 + Time Remaining + + + + + + 67239488 + 67110912 + Text Cell + + + + + + 2 + YES + + + + favoriteColumn + 2.300000e+01 + 1.000000e+01 + 2.800000e+01 + + 75628032 + 134217728 + 4pmlA + + + 6 + System + headerColor + + 3 + MQA + + + + + + 67239488 + 134219776 + Text Cell + + + + + + + + + 3.000000e+00 + 2.000000e+00 + + + 6 + System + gridColor + + 3 + MC41AA + + + 1.700000e+01 + -1010827264 + 2 + 15 + 0 + YES + + + {{1, 17}, {458, 95}} + + + + + 4 + + + + -2147483392 + {{224, 17}, {15, 117}} + + + _doScroller: + 3.700000e+01 + 1.947368e-01 + + + + 256 + {{-100, -100}, {223, 15}} + + 1 + + _doScroller: + 7.689655e-01 + + + + 2304 + + YES + + + {{1, 0}, {458, 17}} + + + + + 4 + + + + {{20, 60}, {460, 113}} + + + 530 + + + + + + QSAAAEEgAABBmAAAQZgAAA + + + + 292 + {{47, 19}, {54, 24}} + + YES + + -2076049856 + 134219776 + + + -2034220801 + 162 + + + 400 + 75 + + + YES + + + 1048576 + 2147483647 + 1 + + NSImage + NSActionTemplate + + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Remember Identity + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Forget Identity + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + VGlja2V0IE9wdGlvbnPigKY + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Q2hhbmdlIFBhc3N3b3Jk4oCmA + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + YES + 2 + YES + YES + 2 + + + + {500, 273} + + {{0, 0}, {1440, 878}} + {400, 295} + {800, 822} + SelectIdentityFrame + + + + YES + timeRemaining + isFavorite + principalString + favorite + identity + + Identity + YES + + YES + YES + YES + YES + + + KerberosTimeFormatter + + + KerberosFavoriteFormatter + + + 7 + 2 + {{196, 142}, {427, 368}} + 603979776 + Window + NSWindow + + {3.40282e+38, 3.40282e+38} + + + 258 + + YES + + + 266 + {{78, 326}, {329, 22}} + + YES + + -1804468671 + 272630784 + + + user + + YES + + 6 + System + textBackgroundColor + + + + 6 + System + textColor + + + + + + + 268 + {{17, 328}, {56, 17}} + + YES + + 68288064 + 4195328 + Identity: + + + + + + + + + 266 + + YES + + + 256 + + YES + + + 266 + {{22, 181}, {347, 25}} + + YES + + 67501824 + 0 + + + + + + 1.000000e+02 + 0.000000e+00 + 0.000000e+00 + 0.000000e+00 + 11 + 0 + NO + NO + + + + + 268 + {{11, 213}, {185, 17}} + + YES + + 67239424 + 4194304 + Get tickets that are valid for: + + + + + + + + + 266 + {{21, 159}, {349, 14}} + + YES + + 67239424 + 4325376 + 10 hours + + + + + + + + + 268 + {{11, 134}, {133, 17}} + + YES + + 67239424 + 71303168 + Kerberos 5 Options: + + + + + + + + + 266 + {{40, 36}, {311, 25}} + + YES + + 67501824 + 0 + + + + + Helvetica + 1.200000e+01 + 16 + + + 1.000000e+05 + 0.000000e+00 + 2.484663e+04 + 0.000000e+00 + 8 + 0 + NO + NO + + + + + 268 + {{22, 88}, {303, 18}} + + YES + + 67239424 + 0 + Get tickets without IP addresses (NAT mode) + + + 1211912703 + 2 + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{22, 110}, {351, 18}} + + YES + + 67239424 + 0 + Get tickets that can be forwarded to other machines + + + 1211912703 + 2 + + + + 200 + 25 + + + + + 268 + {{22, 66}, {248, 18}} + + YES + + 67239424 + 0 + Get tickets that can be renewed for: + + + 1211912703 + 2 + + + + 200 + 25 + + + + + 266 + {{39, 14}, {313, 14}} + + YES + + 67239424 + 4325376 + 6 days, 17 hours, 45 minutes + + + + + + + + {{1, 1}, {391, 242}} + + + + {{17, 48}, {393, 244}} + + {0, 0} + + 67239424 + 0 + Ticket Options + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 1 + 0 + NO + + + + 289 + {{331, 12}, {82, 32}} + + YES + + 67239424 + 134217728 + OK + + + -2038284033 + 129 + + DQ + 200 + 25 + + + + + 289 + {{249, 12}, {82, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + -2147483382 + {{73, 328}, {337, 17}} + + YES + + 68288064 + 272630784 + Label + + + + + + + + + 268 + {{18, 300}, {184, 18}} + + YES + + -2080244224 + 0 + Use default ticket options + + + 1211912703 + 130 + + NSImage + NSSwitch + + + + + 200 + 25 + + + + + 292 + {{14, 12}, {127, 32}} + + YES + + 67239424 + 134217728 + Show Options + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + {427, 368} + + + {{0, 0}, {1280, 778}} + {3.40282e+38, 3.40282e+38} + + + + YES + forwardable + renewable + renewableLifetime + identityString + favorite + addressless + validLifetime + renewableLifetimeString + validLifetimeString + hasCCache + minValidLifetime + maxValidLifetime + maxRenewableLifetime + identity + renewable_lifetime + valid_lifetime + renewal_lifetime + identity_string + canClickOK + usesDefaultTicketOptions + + YES + YES + + + + + YES + hints.explanation + + YES + + + + + YES + minimumValidLifetime + maximumValidLifetime + minimumRenewableLifetime + maximumRenewableLifetime + favorite + identities + minRenewableLifetime + content.identities + + Identities + + + + KerberosTimeFormatter + + + + + YES + + + kerberosIconImageView + + + + 300158 + + + + headerTextField + + + + 300163 + + + + explanationTextField + + + + 300164 + + + + cancelButton + + + + 300165 + + + + selectIdentityButton + + + + 300167 + + + + cancel: + + + + 300169 + + + + window + + + + 300181 + + + + identityArrayController + + + + 300184 + + + + enabled: canAdd + + + + + + enabled: canAdd + enabled + canAdd + 2 + + + 300210 + + + + addIdentityButton + + + + 300214 + + + + content: arrangedObjects + + + + + + content: arrangedObjects + content + arrangedObjects + 2 + + + 300229 + + + + selectionIndexes: selectionIndexes + + + + + + selectionIndexes: selectionIndexes + selectionIndexes + selectionIndexes + + 2 + + + 300230 + + + + formatter + + + + 300242 + + + + formatter + + + + 300245 + + + + delegate + + + + 300251 + + + + identityTableView + + + + 300252 + + + + cancel: + + + + 300253 + + + + value: arrangedObjects.expirationDate + + + + + + value: arrangedObjects.expirationDate + value + arrangedObjects.expirationDate + + NSConditionallySetsEditable + + + 2 + + + 300255 + + + + sortDescriptors: sortDescriptors + + + + + + sortDescriptors: sortDescriptors + sortDescriptors + sortDescriptors + + 2 + + + 300259 + + + + select: + + + + 300293 + + + + delegate + + + + 300325 + + + + delegate + + + + 300328 + + + + identityOptionsController + + + + 300357 + + + + value: arrangedObjects.favorite + + + + + + value: arrangedObjects.favorite + value + arrangedObjects.favorite + 2 + + + 300367 + + + + identitiesController + + + + 300380 + + + + hidden: selection.hasCCache + + + + + + hidden: selection.hasCCache + hidden + selection.hasCCache + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300421 + + + + hidden: selection.hasCCache + + + + + + hidden: selection.hasCCache + hidden + selection.hasCCache + 2 + + + 300422 + + + + hidden: selection.favorite + + + + + + hidden: selection.favorite + hidden + selection.favorite + 2 + + + 300438 + + + + hidden: selection.favorite + + + + + + hidden: selection.favorite + hidden + selection.favorite + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300440 + + + + addToFavorites: + + + + 300441 + + + + removeFromFavorites: + + + + 300442 + + + + newIdentity: + + + + 300450 + + + + editOptions: + + + + 300452 + + + + cancelOptions: + + + + 300453 + + + + doneOptions: + + + + 300455 + + + + ticketOptionsOkButton + + + + 300459 + + + + delegate + + + + 300461 + + + + maxValue: selection.maxValidLifetime + + + + + + maxValue: selection.maxValidLifetime + maxValue + selection.maxValidLifetime + 2 + + + 300470 + + + + minValue: selection.minValidLifetime + + + + + + minValue: selection.minValidLifetime + minValue + selection.minValidLifetime + + 2 + + + 300471 + + + + validLifetimeSlider + + + + 300473 + + + + renewableLifetimeSlider + + + + 300474 + + + + sliderDidChange: + + + + 300475 + + + + sliderDidChange: + + + + 300476 + + + + maxValue: selection.maxRenewableLifetime + + + + + + maxValue: selection.maxRenewableLifetime + maxValue + selection.maxRenewableLifetime + 2 + + + 300481 + + + + minValue: selection.minRenewableLifetime + + + + + + minValue: selection.minRenewableLifetime + minValue + selection.minRenewableLifetime + + 2 + + + 300482 + + + + staticIdentityField + + + + 300483 + + + + identityField + + + + 300484 + + + + changePassword: + + + + 300486 + + + + value: selection.identity + + + + + + value: selection.identity + value + selection.identity + + NSContinuouslyUpdatesValue + + + 2 + + + 300489 + + + + value: selection.forwardable + + + + + + value: selection.forwardable + value + selection.forwardable + 2 + + + 300490 + + + + value: selection.addressless + + + + + + value: selection.addressless + value + selection.addressless + 2 + + + 300491 + + + + value: selection.renewable + + + + + + value: selection.renewable + value + selection.renewable + 2 + + + 300492 + + + + value: selection.valid_lifetime + + + + + + value: selection.valid_lifetime + value + selection.valid_lifetime + 2 + + + 300494 + + + + value: selection.hints.explanation + + + + + + value: selection.hints.explanation + value + selection.hints.explanation + 2 + + + 300495 + + + + glueController + + + + 300496 + + + + enabled: selection.renewable + + + + + + enabled: selection.renewable + enabled + selection.renewable + 2 + + + 300497 + + + + formatter + + + + 300499 + + + + formatter + + + + 300500 + + + + value: selection.renewal_lifetime + + + + + + value: selection.renewal_lifetime + value + selection.renewal_lifetime + 2 + + + 300501 + + + + longTimeFormatter + + + + 300502 + + + + shortTimeFormatter + + + + 300503 + + + + value: arrangedObjects.identity + + + + + + value: arrangedObjects.identity + value + arrangedObjects.identity + + NSConditionallySetsEditable + + + 2 + + + 300504 + + + + value: selection.identity_string + + + + + + value: selection.identity_string + value + selection.identity_string + 2 + + + 300506 + + + + value: selection.identity_string + + + + + + value: selection.identity_string + value + selection.identity_string + + NSContinuouslyUpdatesValue + + + 2 + + + 300509 + + + + identityTableScrollView + + + + 300511 + + + + ticketOptionsBox + + + + 300520 + + + + toggleOptionsVisibility: + + + + 300521 + + + + ticketOptionsWindow + + + + 300522 + + + + ticketOptionsToggleButton + + + + 300523 + + + + value: selection.usesDefaultTicketOptions + + + + + + value: selection.usesDefaultTicketOptions + value + selection.usesDefaultTicketOptions + 2 + + + 300525 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300527 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300529 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300531 + + + + enabled: selection.usesDefaultTicketOptions + + + + + + enabled: selection.usesDefaultTicketOptions + enabled + selection.usesDefaultTicketOptions + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 300533 + + + + enabled2: selection.usesDefaultTicketOptions + + + + + + enabled2: selection.usesDefaultTicketOptions + enabled2 + selection.usesDefaultTicketOptions + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + NSValueTransformerName + + + YES + + + + + NSNegateBoolean + + + + 2 + + + 300535 + + + + checkboxDidChange: + + + + 300536 + + + + contentArray: content.identities + + + + + + contentArray: content.identities + contentArray + content.identities + 2 + + + 300539 + + + + enabled: selection.canClickOK + + + + + + enabled: selection.canClickOK + enabled + selection.canClickOK + + YES + + YES + NSMultipleValuesPlaceholder + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSNullPlaceholder + NSRaisesForNotApplicableKeys + + + YES + + + + + + + + 2 + + + 300546 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + 5 + + + YES + + + + Select a Kerberos Identity + + + 6 + + + YES + + + + + + + + + + + + + 8 + + + YES + + + + + + 15 + + + YES + + + + + + 16 + + + YES + + + + + + 100008 + + + + + 100015 + + + + + 100016 + + + + + -3 + + + Application + + + 300118 + + + YES + + + + + + 300119 + + + + + 300156 + + + + + 300183 + + + Identities Array Controller + + + 300196 + + + Short Time Formatter + + + 300206 + + + YES + + + + + + 300207 + + + + + 300216 + + + YES + + + + + + + + + 300217 + + + + + 300218 + + + + + 300219 + + + YES + + + + + + + + 300220 + + + + + 300221 + + + YES + + + + + + 300222 + + + YES + + + + + + 300223 + + + + + 300224 + + + + + 300225 + + + YES + + + + + + 300226 + + + + + 300244 + + + Favorite Formatter + + + 300294 + + + YES + + + + Ticket Options Sheet + + + 300295 + + + YES + + + + + + + + + + + + + 300296 + + + YES + + + + + + + + + + + + + + 300300 + + + YES + + + + + + 300301 + + + YES + + + + + + 300302 + + + + + 300303 + + + + + 300329 + + + YES + + + + + + 300330 + + + + + 300331 + + + Identity Options Controller + + + 300334 + + + YES + + + + + + 300335 + + + + + 300370 + + + Identities Controller + + + 300426 + + + YES + + + + + + 300427 + + + YES + + + + + + 300428 + + + YES + + + + + + + + + + 300429 + + + + + 300430 + + + + + 300431 + + + + + 300432 + + + + + 300402 + + + YES + + + + + + 300403 + + + + + 300462 + + + Glue Controller + + + 300485 + + + + + 300498 + + + Long Time Formatter + + + 300308 + + + YES + + + + + + 300323 + + + + + 300309 + + + YES + + + + + + 300322 + + + + + 300310 + + + YES + + + + + + 300321 + + + + + 300311 + + + YES + + + + + + 300320 + + + + + 300307 + + + YES + + + + + + 300324 + + + + + 300315 + + + YES + + + + + + 300316 + + + + + 300312 + + + YES + + + + + + 300319 + + + + + 300314 + + + YES + + + + + + 300317 + + + + + 300313 + + + YES + + + + + + 300318 + + + + + 300514 + + + YES + + + + + + 300515 + + + + + 300518 + + + YES + + + + + + 300519 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + 15.IBPluginDependency + 15.ImportedFromIB2 + 16.IBPluginDependency + 16.ImportedFromIB2 + 300118.IBPluginDependency + 300118.ImportedFromIB2 + 300156.IBPluginDependency + 300183.IBPluginDependency + 300196.IBPluginDependency + 300206.IBPluginDependency + 300207.IBPluginDependency + 300216.IBPluginDependency + 300217.IBPluginDependency + 300218.IBPluginDependency + 300219.IBPluginDependency + 300220.IBPluginDependency + 300220.IBViewIntegration.shadowBlurRadius + 300220.IBViewIntegration.shadowColor + 300220.IBViewIntegration.shadowOffsetHeight + 300220.IBViewIntegration.shadowOffsetWidth + 300221.IBPluginDependency + 300222.IBPluginDependency + 300223.IBPluginDependency + 300224.IBPluginDependency + 300244.IBPluginDependency + 300294.IBEditorWindowLastContentRect + 300294.IBPluginDependency + 300294.IBWindowTemplateEditedContentRect + 300294.NSWindowTemplate.visibleAtLaunch + 300294.windowTemplate.hasMaxSize + 300294.windowTemplate.maxSize + 300295.IBPluginDependency + 300296.IBPluginDependency + 300296.ImportedFromIB2 + 300300.IBPluginDependency + 300301.IBPluginDependency + 300302.IBPluginDependency + 300303.IBPluginDependency + 300307.IBPluginDependency + 300307.ImportedFromIB2 + 300308.IBPluginDependency + 300308.ImportedFromIB2 + 300309.IBPluginDependency + 300309.ImportedFromIB2 + 300310.IBPluginDependency + 300310.ImportedFromIB2 + 300311.IBPluginDependency + 300311.ImportedFromIB2 + 300312.IBPluginDependency + 300312.ImportedFromIB2 + 300313.IBPluginDependency + 300313.ImportedFromIB2 + 300314.IBPluginDependency + 300314.ImportedFromIB2 + 300315.IBPluginDependency + 300315.ImportedFromIB2 + 300329.IBPluginDependency + 300330.IBPluginDependency + 300331.IBPluginDependency + 300334.IBPluginDependency + 300335.IBPluginDependency + 300370.IBPluginDependency + 300402.IBPluginDependency + 300403.IBPluginDependency + 300426.IBPluginDependency + 300427.IBPluginDependency + 300428.IBEditorWindowLastContentRect + 300428.IBPluginDependency + 300429.IBPluginDependency + 300430.IBPluginDependency + 300431.IBPluginDependency + 300432.IBPluginDependency + 300462.IBPluginDependency + 300485.IBPluginDependency + 300498.IBPluginDependency + 300514.IBPluginDependency + 300515.IBPluginDependency + 300518.IBPluginDependency + 300519.IBPluginDependency + 5.IBEditorWindowLastContentRect + 5.IBPluginDependency + 5.IBWindowTemplateEditedContentRect + 5.ImportedFromIB2 + 5.NSWindowTemplate.visibleAtLaunch + 5.editorWindowContentRectSynchronizationRect + 5.windowTemplate.hasMaxSize + 5.windowTemplate.hasMinSize + 5.windowTemplate.maxSize + 5.windowTemplate.minSize + 6.IBPluginDependency + 6.ImportedFromIB2 + 8.IBPluginDependency + 8.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{704, 346}, {427, 368}} + com.apple.InterfaceBuilder.CocoaPlugin + {{704, 346}, {427, 368}} + + + {10000, 354} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{610, 271}, {203, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{495, 457}, {500, 273}} + com.apple.InterfaceBuilder.CocoaPlugin + {{495, 457}, {500, 273}} + + + {{503, 256}, {419, 465}} + + + {800, 800} + {400, 273} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 300546 + + + + YES + + BadgedImageView + NSView + + IBProjectSource + ../Sources/kim/agent/mac/BadgedImageView.h + + + + FirstResponder + NSObject + + IBUserSource + + + + + KerberosFavoriteFormatter + NSFormatter + + IBProjectSource + ../Sources/kim/agent/mac/KerberosFormatters.h + + + + KerberosTimeFormatter + NSFormatter + + + + SelectIdentityController + NSWindowController + + YES + + YES + addToFavorites: + cancel: + cancelOptions: + changePassword: + checkboxDidChange: + doneOptions: + editOptions: + newIdentity: + removeFromFavorites: + select: + sliderDidChange: + toggleOptionsVisibility: + + + YES + id + id + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + actionPopupButton + addIdentityButton + cancelButton + explanationTextField + glueController + headerTextField + identitiesController + identityArrayController + identityField + identityOptionsController + identityTableScrollView + identityTableView + kerberosIconImageView + longTimeFormatter + renewableLifetimeSlider + selectIdentityButton + shortTimeFormatter + staticIdentityField + ticketOptionsBox + ticketOptionsOkButton + ticketOptionsToggleButton + ticketOptionsWindow + validLifetimeSlider + + + YES + NSPopUpButton + NSButton + NSButton + NSTextField + NSObjectController + NSTextField + NSObjectController + NSArrayController + NSTextField + NSObjectController + NSScrollView + NSTableView + BadgedImageView + KerberosTimeFormatter + NSSlider + NSButton + KerberosTimeFormatter + NSTextField + NSBox + NSButton + NSButton + NSWindow + NSSlider + + + + IBProjectSource + ../Sources/kim/agent/mac/SelectIdentityController.h + + + + SelectIdentityController + NSWindowController + + IBUserSource + + + + + + 0 + ../../../../../../Projects/Kerberos5.xcodeproj + 3 + + diff --git a/krb5-1-7/src/kim/agent/mac/resources/Gear.tiff b/krb5-1-7/src/kim/agent/mac/resources/Gear.tiff new file mode 100644 index 0000000000000000000000000000000000000000..c1382588f21ed6dd329a4925404fd06744f2fb71 GIT binary patch literal 22360 zcmeG^2Y3_5(tE0wEO%otRW@!wWLa{Td$++2cRI2p+rqLWRB!=84L!5~p(WG@0TODc zp_>Gf@MxhWkYFGL2n3vj7K-)Ho+Mi~wt>8teD8nHr|<4&XJ=<;XXj?;c5juIhI%4| ztWXD3hiCv1aN-M|LlM_S1yh4&JRrUOH;?mO618^8d-K#dXA*3R1zxnj*4W5SBNUg z)MYZAm|Ib%P-;aL5#C~4w+LX2=6iEV5?yJ8cR^YvSEo`bO65APzpo!p81fdkNFy$j zm8&$RT!C+pH!##li$q!Ri6(ZCitsMc>C_@Vzr4KMx7^=Xr77kMLPJCOenP%b$O8(V zwo<7RSMZeD?ob;khPH>_6sJCIQhV$)|`Ae|E01P9HlCW9{jToI2wmO zK)~qH;3hwO*qj$91WMFH^{{GPUr?3QQd>m57Q|nliC2QeGx5mXSUzoZoAz#9>_Sy!97-be#)MBHXwZR&a>4ZIO? zn{~CR>y0$)4y539!4GSGIC9H0g!!kx^Sbw3wFC;c4jfU5p z5MnmMd6GE$M9yzhy>{h&w|ObCV)NSB<(QuOGtTR>8Q7L7xFcj5JWn6t4yz3AT$xe= zlZDFS2>0BaL|%wHUNCWs&xp(Emzls-D_~NYo0%J%ni9u#=kfV5YPCYfjZ>AW^*Wh` z&yUZE=Vqp+Waq%rh##MyknYZPw^#}hV{&p)0|>SJOpQt{)95Nwfh!LR_)2wBcc{-; zO(VGgE0s%hk!)6YsjM;*)1WFSHo7E~~xlUFVqtS>f8(52R z5(I;SX3<*U@#@B5CLp>3CeC3B2?LmKs}e~Ra+tEJ7YB&nq^+&lVIWU(c4m_Tkk zaUCiO3=jo`_J>I^ob^h1VFpwuOH_!9ExAJ1%b*t`VdmQmk_zRUH5$%0s~PHfUHi$< zVAY86N`$$x`YvkL`u_h|Pcu!!c4Af@EbE!US9VC70k!CWvL#{#_=x{D<7v{YdZz16QN4G)6j1uhq$<7?~xLGz6CQR@izp+9dFP z!)Ua%sO;s?n-y*j3bEqMp(2J~`D)Q(GjVAPu8<;!L_c2$O&bQsSD=Ia1Dc}_3=V39 zZWv&o*5-vaN2E=I{5RBV>)c-s^FfjB0k+7T&B`!#BHy*Yvi&>N4LBaqD zHLYBw`0p9f{{w8SmA1Cv8vo~qbwP8}cda^wzhzi&@EewW3fRAJT>lR<;HHgj!Gc>D z#alrC7Y^?K;TEh`OaB)J_?DV!G05j;b5q*}dA!Q;ZyDrGAz(~q3e2nEb-#w#(G*qr z`S}XrHS6^jwqW^f1ibR4swAZijEckxt&ES?bXto-b@0J^Lz(7RpI~9nSsJ!tK;Qnnq$YNt!#};GmQ+dZ)0l(Et_brxM`T#Fpbi*iRKo<4j#Pj8p$TtZf}$8 zx)tQ!ykrDB>|h=E2THWzp5Y#qLCK;P(|xGV$sK*>+=~<+yh{&B;e>sNRB~717z4l< zTYr>TAy;BHndH_ZUjj%Oej(BJWbK#>mIChNTC^9LXWLLPYAhmGsj2r!oDC;OBUWl* z&jTzqR~px^+mSh4;cA0&kOqm75^0ed?iwTmSb{1|JnoZ}z};XVA!rq0zVgW+GvBQ=9rCQ962mKyJflhg>f7~6`I2*FNOgmq6tNzj+LM@e3AZG2eT zBBsaX8XcAd<_wcyIH}Yt6mY}hGhjocQmV};943L3sa%#sCx8@bAUUwTRH0H9Lz+BN zWkov6bgWKQW=fM{WEGc~^RZ|QtwJu5Y4a4RT1XL%>Y zx4*jmRM`8HlTeTYRhg8FmERbXrY)8=!Z5@NU5>c85zba3gL1M8U5Yk2CoQ!Qc8Fny zR%Ub~VpfStQx&6-7n?O@XKXxt?qNhjNv2d*B-Sf*0J28Fl3Fw5csYSYHzv0(EGGB2 zS}51S$UiozJ_CxNbd?h8nx#{zGxR#G%xoAqkF5YhdI`%ZRO!H=Ucy^L7nd|8C!a_k z%nWhhB%*3b*!XP19&I?V3DZeBOo6D_dt$YjpPE!40S!?8fc@x%;i91i+4oLNNra8( z*i(bAHvED(n- zbs!AiL(?gSBSaKPNhiny1jYvy8b_lum{u&dH4H?JGYLeYnltSYK_jRX8imeeSkb8* zf5>#8(%c*c^q9V4C->pwgbe37E4IXT_h^@OsL($^GyZfO({pZi?bTl;+CZ0;TPJwM zzn3FTIJ`<1)c#EFHQ8_5CRTr=zy5oo_q^5bd^-Qg*&iSLWBcdlZamB@8Zl|XnjK%9 z|LIY1Qhssy^;*PS^T- z6kgSgpBtCmPNEI?)suk*V0r}}J_ACmYA;R54bsW3)r-)w1l|oI7`{UsDp{ukib7|9 z9z9^4{=~ZX&g{v{7S{f@(2C{~_^$Ye``QP4m8bhgZZasB!F4 zG-HG0+s|&lUH;M5r&rRx?2_-l?m_D1ygdu3?@paqaOcA_BMPo;J2U7(dDYCf&z1kY zsm}=SfuRw7g6+I6PrLXySF%tuVC24EHl3+_*kkM3k)zl3_*pdh{D<#+BOEmKgSqm3 z%N@TNv^I%Vy7*DvPhrn|GYly7Y1I8I2DEv1x2G|_8)iMMx_mtUVes{xJ=fkl>ay>X z;Zcdy!DCV$EO~JtZODs^I=i}Qy~h~7H9j$Jq zBKDLhB_WQh1tJWa4iM?ld7}^ghL@bl<(e~I^X?!~Yv4&IGJ)P-3V#a#@I-(W=cI2yy!G9?T%6fCn^S|-Kt5rC(R(Bt8U3f=`x z8X=dJ1AG=>4~4!=4ls^joXccl7!qmNFL~%>k`jRZ0On|Nvf=;^2j9*qwtx#QU>%GD zK#Ss3>Ppfxa(yH{xbU|LA>3qHIiBd{Wx~Hbh&593gF~^h5`sUn&A1eD#Jc5zl7j@H zK|wsBFCOj9N2{4;qF3B;-x^7N?@RU>;c~nI*HE|tr&dhm|Y^{@|qg)pDt)2mW3Q|!R~4qem9VD^T5jBJ1XdIrBqJ--GyA)QV;*hViq!B z&}i2HIIXTj&O>~W{Yhs;{pC2KIawp>zz-pZsPDH_Rvx$zgz~%HG}=ADkWXG4T`034 zNzuy5;0(oO%?Kk24d3YSj$wzKVFd4rx+5RNLqZgc!ca6yK)q20yc6|9gW)Zx z1eHPjT#iPeacB~nj%K6zXfaxbR-<)jBif2~qP^%4`T~88PN8$?5~@Kr&>d8Z9-(J2 zS~3Y6!ijJtx)Gj4FG5I!5RpUzkxFC{{fMDNF`*>%#3*6{F`bx8EGAYE>xeDHZsHK} zC2^YgmbgmXCVnHHQm7OT#hKED;zi+8LMSnmK9n5FAWAW1IHig*kusCAkg}5UF=Yqk z5anyiIZ6%X4&@>I$&EGDh3ZD-QA4P4)C_8WY7tdKeVaOsx`4Wpx{F{)oX~xG=mK!Hi@^KgKY|NX87t2aHXOgN)OR>x_p?CexMK ziy6VpV2YVK<|O7K=Euwf%rndz%qLdXR^6qt&~>dtrl3Vx7u%Y#_FckGnPHe zlO&@23tgl-C!ExmD;oVA>ToNqb5+t}E6*+kp)x6#?mv{`3UZS#Z8 z6I&-+U)vO0sqGlsCAK?k&)D9xW7&Dy#n=tDtFl{Qx6SUP-CcW@y_bEQz1aS3`z7|f z?Jw9rbZ~MIIAl1KIm~ca@9?F=Ek~xKmt%sX)N!KYD#vQa>rPas?oM$|5~m4HtDQb~ zy5Y=l_I6Hj9_BpV`4i_8&b93v+Xb}CYgf^3NxOaRYFwx;UM?vv3YS?fTV2k(JZ;~l zeN1~<`>E|Wwm;MUafePFqC3bsOzW_z!?_MmUAe9auBEPXTz9&D-;vg_XUD!B%R7G9 z@$-&%J2`g>>m=zkt<%;{-*u*R?%6r3^T^JtIv?-+uuIo2NnO-k7Imraa<{8X*XXXp zy3Xsmzw7O8PTeBA$-B+#cA(qO+;-d;u7bOedxTr-*4ZuDP4BkC?S$JicW?Jx_wnwV z+`sS6?jF*;sQbL`hr8E$bn{5_80E3S<2z55XNYHs=lh;VJs*2{d*ypg_S)%n%e#Yj zig%Uw2Jg#0Ha<~4!+lozobAEr5z?cy#|J%5^`!I+>{-%tNzaqLD7}Ju$$Nd!>-1an zw?f}izP0kL3p@@lhBtz@fp^u{#W&S=yzfrmdwdUmfBqc)QGT6Ypr68TwcjOyqoB87 zykL*uH(^hqM7TtF*5AfI(SMBpF8^NxdIiV=J`A`R=oFY1I63fe;ESN(AWhK5pxeP7 z!9#eOQY9B-;C)IGc4xgn0v8)v6|TJv5(_Kaiil7 z##7^y;-|%*NN`NZO<0`pL!x_PapH!=+N8jwkx2)W>B)VP=OkZ9>5?KzS(j4VJGl4g z-beay`egT6+~-z9$QqS(G}|eANcQ^dM>(-MvvMxw`sC_!59itC4a{4Y_c%X3e{OzF0l#2$!Posd z_LKM9)t}ivum76<4+kU+m_Ojgz`%i%2A&_}J*Z;PmxDVFRt(-Z#BPXq$hM*Mq4`7C z4}C7q5U&(JEKDg}T39QIle{mvBaN2Mlirp^$mYs!7DW`zExJ`4QT$%Xf>9*br#dcL@1@wp|jOExX-ymac)#~(;PIP+ojhZ~o5SvGyy)8+Ez7gr>$ z*s;=U<$_g=RU=mYv^sC~(SL;eW8IpLYo@Pxu~xaZ=A*2Sj;sq_w{Css^|LlmHt09p z{&?WWr#^}QWY-6s4yASUP+q3;M-_O?Wb=$jSU%P#?_Otg-+;2Egb>QJa^})M`iVs~s zJmm1D>VoRCNBSN)@p+%mkA0E&MfK5`qX&*f9NYV)=*!(-g?zR1>!7c991lFc{hxvV z+mzhCe}=O0#H>2YOKO;F9gtMONlU(3FB>AK|logcM7KEE;X zC!3!Z-0XI9-7Vp*y|)u@pZa;g&o}OxIZ=@*AzmfrKZ_v!uU`^RewYH$3i`PJ~- zjNe^^{5kXa!WTVW?5XQhciB*8 zFpNdq%n%P38*0+wA$O+?MZ@h-=fda?;d#9FGZG80`gBNVc#PY^oxJVz?H?~GgAt{# z$2j(+IO_82$2za4{W9*eRoT0LbnZQ6dC;O9KXjzf4|U5}dv)sir6;Sxe;A5}26RMy z@)CUlItR(tQ0Lp#MqkAjH!|f?V~T-N9_NpYFcg7 z_k;bYJCCFCs%X0_L($jwk!tF*g5W`gzopehqo^9>0s2`Aul=WdP*{xBN?VVZnFBPQ zvCL=TNTgi#gcxfhuSGqov#(u=oYL!VWiO9y0Vg6R-$K_yHe6&Qm(w$xr!&<j_@aKFUEeF78)ud5;aeX>)jdA33XSTuB*8VlZ@|f0-T4Pj zAs;qnIl+#dJ!f%G$K~SW3Be0|){P0Bddqd=gbBwwq<3Q;x~)5qaHl#_5OQlv_)Wig ztS2WICOS;&&Mk`Db?l^%eV$u3eaq;yEyo<@ECm z^3SJF{mJUgyvSuY?kSK}uj_JZJ#3o8 zZThEA=05@A!Y&~(H&y|QN95ajT8;+Kc#?3cxDsZH>8BdS)0m$tqLFj|S1=_^1wrj_ zrQj=`6H~%2Faw0paNsvmd_V%1c=gGFN@W_Z0A6_1@N!AYq0lSg?G|;0lY>%W{<;#T z4m5}hZ}(h?$W<_BUy195KN7?<+cX8pO{Od5@U~29f{N1;MWF(xL0pnAd~RD|$|uvM z%2JhOTA@`JHA+hqm_Mm{xRYgyDl}>U?Qy!%LBQ;T1N>ON7b zE}4>)i0C7WbK_%|)gkt>*!bMykvIp{#TXDB?vb&Pb;}uW#jNY94Tu^GkX_^`(RQ(oO0UzN9{(uo?9U zg_i1zA=MW{stVtb@^$E@D6E;fK`ZMpTI;VQ)u%M7Pl$w| zK8e4?*!X8cllp|OZGFwDZ#)_X>KkvgzSh*2Rd0Qm3al@E>z1v5T79Fy`Wnu7{_GkYG$KweS literal 0 HcmV?d00001 diff --git a/krb5-1-7/src/kim/agent/mac/resources/KerberosAgent.icns b/krb5-1-7/src/kim/agent/mac/resources/KerberosAgent.icns new file mode 100644 index 0000000000000000000000000000000000000000..c6a725213c8f6ded5b4a56c944d4e66f86434211 GIT binary patch literal 40494 zcmeFa1$3;|M%Ye|9!vjh9a5FthM&?z1Oo(PaZvck)k~2oV>Jf0Yx2p zm%`Wh3w{Ms^tjTahhxd3_=oD_`}giYyjL?qO&TA6^qWj7yL<1!Z;cX472l3Zq@&DT z#ozAb4&$xL4@M*-W8Axn_r`n&*`ME)N@a%lzEic2{QMz#zu{danRG!(%uUU-l&qCT3AsWSHlt!50TF(j>)84$@J0sk11*| zm5?aNDQs%3EKS&3LEdz4NZ2a_;ZdofL}4V8rl#@&GBO4Ay}ez{WvRTqdrK%auo~-W z>m0z_WKtu^1gX?fV=*r+JG+wURq5-jN#pT~Kui6hOgzxjCmq8|A*iWDUDki~Mo3y# zQ8&}8+SgZ;o#uVHfSL|<$a;okqoa34?R{f+@5;b>vQ#=El}N{`jKWfK+nC-7eSIwj zIfBgKYkPB90ignjymwY(ZX1i^&#`F!lT{=gkW37VfHep{aKAW3Y zP*_x4QktLSmqNWZ{$LyeclFA~#w0y`{nAnCV4tvSh%1>rB1-;x##^5r`Qh-jOcDH~ zHm|OuK1YDh%L!Ce6eU|}Cc-5iJh&&7j&jB(j}8rpL_;EpSUlJ>$dP<9(#L;o_VQb1 zj*i^uL8)X!nqOR&l?@s4^9zbgOUuhD%Zmk`I`Py@7)RVA9vc&hWYW>GvC*N9mL6K7 zJk-(FC#EHzN_!$coTFoHmy&cRMI@C-WW8B&NtxM1hh_E6&8@Xn)m0URF(xt8tK$zI z{Wj3kFBuyf>g?)~j>#mFfv!GUGH(dXJI3DV1ae#bxB=Rdr;Uoc;B@O?E|9ZC!n3Ax|%y4NaLuEEyaSOJwxeba8hd zL=p844)=>B5>ak46~DEU9!TIwCo%SeSSA`y)pW9lVuLURB@F zP*cn|34x!@x-XT;#^98~w!yKnk-nDZK8a+wtFx_31dS<(M2uvD?A}miQC0u_$D{g^ zS+dTksMNZ4`shu4Lle%A#@V3O*wj!K@5m3LR7H<|CvnY;&FpP!>qbxvwRa8n4@-u7 zgo6VE9LeNi*i|xe|H0h{j~|X2NZyv-tqqE=OE^m#SyqOgzFJqeS!oeoH2SOj|b=JJjFa!;vTsw)Zj;WhARn#P-|L(ZYyQzJsBqt-X^I z?^bvNh&8vgG}jgSIcoZlP<(h_Di)9Ek4+kt4s>Fv;@&QzHKm@8u3nHE>g>0cyd#xK z5>jJ)jjiqM9i1F_>GedUmX_A`*3w`{O)qMK^wHxn$;gOUEQ7nkB7IHm!~nhB!|=Aj z{=tD^BsEdrppE2R>8LO%F51e{*3sVCDW0s3P-<=OY^zMQ(bIIN-Wb3C=pll3bW{qf z!b3*j`29_+{wEH1ck~d-eZnC|qBPXk4e@3`XYn~P4vvma-ih^%AlTf(w5qjtwbx}^ z=xMqVe|z{Fh#&+;CHNC5R;)ZA91;`h`dgaX2C?A5*5(0_>}_fvvX)Gj4kzbS6ePt) zXE!uAu_AInv9qJ4=#C?wM@<{Ug2iOPBV%JSP?m7TlZLzd1_mXP{*JC55L6Zk+xuW3 zrJ=4)P@E~!Tdph5#Ew!C zJs_s#jw)fXprRr|7U~mmB-004J79?+Vb{Pg!hd*hXxIXzWZk*GF@mxhLJF2OX;tZ} zEpW4Uw4qelB}!!mqmurm_*Rrk2P(5<#Bh`vu@u9-gdIcB&tOkiABj=Lo+c6q!@@q6P=A!KCqFsA zqE5axlUB8^?v!vIv~EeMj66g%$v{YIBUX|O_6~6*6Nh{Hv7VtJI4y_`w)Ppr9mWO{ ztj+wR)1S~G0;#w6)p>ZjI@{@)Q)<<}JtBc5(;rokN$lVYgCr-4`?^}XAd=ERYm*Rv zi9pj(GJRyMJ=B8h6P2D@Qdw6|G;Y$WB#ivXMCd4^2;h~s%jeuJ@wAvDjS}&qrIIOHBt8H z@hAcct{|m}fR5rxgFW3{{g7~Qa9GSpCW(dy1_ohHVN(Y}b*6MwEa2U^TV zH#TF%6WfQnJ$O70Dz!cmt3%y` zjO5jk(XL3FD~A4&3E8C;uxbM+Ha8o#PHgKRiZ$UmJMqlSK(qHZvT}(?9{ysft5~VK zoed}GvK5P05(_(r3?#2%%>hQ2twZBdG78J9SkG-~YG?w%?%_NWS7#?@dn-L7N<#_@ zOJ%YVu?WE>lZY&_S|jmfc=2#=FCt5bGyuzpyShYN$s1UAHjmbI3s1_*EiSLDsA*u+ zNn?{i>!eOmt)-PK&ymN|;~7%QGGxvXMy5hEAd^~(707prD13%u<^Il&9#BQL>POH( z#{*Eo8`80^2%9V1J7G!Lg{74>l@+zfqcDCm-9$Art&`h_gghf250X2c;TcfMz4w2U zj&NnF(1t`T5}Aq>BqRExXn!OIV&%RrVLwgBF>>NRvH@W zM{QCcZ0#B(p#b`?k4p0$nXAqrQHhxaC8bq0sKGUaG}AJp38rjq?GvRLgRrBMy&jKm zNGS}A8Oju-VndOEn39?h!Up2W1Koo|#LdKgtzD?3^QB{bF;aMSE zAO>x!Z{)OSv<>xpneuqf&h~aZo?P~r7|v23N2PfrIQh_85~5e=SW_W zj`k&3UcT-Y9GjMrQ&du3QCU@8P1n4|mZ9b+su>U^njsW<_SR-ZEe4cA-w=mb(p;o3 zCr*u^${{#mVPtJ#S62@-K1({%>~ExF;1eF7mYtPbP*_q?Rb5+CQw>vcT3%^}DO-BP z1x7ABXP%Rtqn;);PH1;Z7@`s@5hGTVjy#o|8ljOn;f$hwVS5h)ok$8CZ|PY1M<%7C z?<>kL0CnOibqz!@bjwUAr=?TeXlVuV4)#_$a`LMDjxmI#w)Qi^n}%&Hs2M~tA5 z52U00P{s>;e*w$ZAsYixlRYP1jcxSJ9OVNTQph+hoTLk3r9yY zvokzu+=x<&>y=3yL^Pts67rddmtfaY>UitCg>MLQ5l9skmzKd~<>ko4jck@{BQn5WKDT>5W(2^R9UzLoC(#$Sjbnp*POara_qT=GR@(Q|Y zQcVr&S0hnha}(X7EEH9kS#fwOjyj+;ZbB*Wx*bF+670D~Wah-JjKm)x-2~{Lx#boV zm6}snSb$$eC8gz+#2|Gbhq}Xs) zkxJ(qXNV80%)Y0m0S9T6G2hk z+0MpPb8!5zTDHdT!JDq8-%_6gCLFQ8tJM+ z2t5h>hK9NZx>=)JRA}r-yv1IRrEEzlu1ObLh-M(+jesVaPV8a91^Y`HafOC#`G~a2 z>Beb8Z+>)2Z5MWRgTvUsjf~xs^{as($<0n3Iwe6kwhlRGQM=))-NO`p|GpF7p>&*u&}XR^xOS=-Gn;m>Njh& z4flGWS~|jy^v>|d$89LZ*8}>EMHFfQN2Vr)UZkiMmP8d@ew?${c>!TDi78b=LUCxg ztE9N3Np}C?XbYkeCAhhX(>!%xC>EL9*};})M$BeMDQ?I^a-}3(nF>(@k`zgW=Hl5> zStIYpY3`k%$hgF$w7RaI-u{8%;Rg6swfMoq`vaf}>v5Z>_K0!~o#9oEHhN_J4wRx% zBT4}!=Ad9=)gxj?WFej{ljfORI%nw{5*442l$=rD-NP=s1-{iV^5Eg4(KeE-=_a~a zwNqSgVdd;Z^HfauBx^WON^b`Ciw#65iZmfQf`uE3jL5?K!fv0r;^ZG51u2tLGHZoB z{n%uR2U{x}2JSw1`1pYkVse_MHMfbncn0#?!loi8N^yU_gd>_nL?juB>}iY$QKU_m ztEcqb1H)rt6O)osQq#&i;Q*kD{iNjHg9ncuKj>*_f+WpN@!g40V1r^9l@)j!htPrsmdl^}^~R$;jx~z55RyJ$n4Grx7Hl z_6(Eh#NHm1(yZ_yv6JX? zv1~B<`l&OPo&li|k)RV7Pga_qky$1jK-Z0cB-(rU__2&Ev~Ms$-vzbIhR3r38Ba=a zTdCAh^o3-!)9upnD-K?Ppc2K310$qo2?Vu014AsCdxXrxu@164;c$+=gR`S6&q{~X z0WV5P)m$jC7kwd>mYSYBs>kyQ3Js5hI57~1I9+Ldld!*EIE0KmDjU1^+vq?Wq0=F% zH?zX#!`_Y!3?Hm2VMuHv`cf<#PQH2Sgt4112(c2yLE%_fMkP+C`WxzyYeq-=+q-*O zkP4WlsjZ?O4|Aj#Ya25X5Pp>6zUmQc(ci?fPPeNkbgbQd0z<;&gyLBLN=qk{I*Qu+ zntP=qZ8f!YJ<~X?scB#^8gdQ#!pFjemv&f+37IoZ)XMJPLfQhFn47->&SJTjPY`TTjV z;~n3i;IN2@C^!I1EIBnJySA&lv#h?Sg)N&bF;Hu2>JU|$Sn(X~ZLG{lrVFB!zONh+ zn~3I$W$m`dzq)Gao|<0O(J5>yY3Z&g z!8*~TT93GS7^QTqVnoapEfC9kJbzj+<;y+Wb{%vM34u$%0z_%? z2`TxNRgImUEu~FewWJDz8Y!EQZEELmfxaE8nuQIUdq7UvTsXoJO_z)|80~pS?VTn2 zk8Ry`$SFEHl8$;u?)8Z&W$hguo$bZ7UA3e`V5>0bfn57=gN2ogo2vs)hX)fxP}@G_ z_sYa5szX^9H%y_Xe5UoC&ZXVE54)wt66r`VCM2Z@>N+~RDoeT=(N)RKK*U4)G9sPC~CicqTS?5r(rYb#=f zV+}z!Xf!tV55ySoT%D|Wa1UxchEkh-F*t&EVaF_nTB-Kwmg5%~!`p{y5jn>sq1^K0A63ZH5pUPd=e=@3<$Vk=>9&niEgTK=}?Q9VOzJ8Pp;yMM4q z&qyG_gN~=Oyu7`Nw25qIkIzCmEki;V6P}y1ja<{&)UsFiUcF#~(>5F9(_j5yoSc`8 ztddsL2KgJ%t+LIRT>gf}fq`&+Y+1*<%yI{du2GOkE}R8**MxBXwXX`Zl5zO$|{>F*TQbNYBK~g6HULW2Ce1VpLsK zKFf$WJZlAX=rl?q&jx#AYP^*Ca(tZP>FHV6IojJ=nO*(P5;Cac!un^{@II<_|EN6&axv^P|lqjjiJRRySdEPpSxqzb{`fdi zu$=|Z0itk@b0aD`I|>}HJ2^U9$pven-hHA`q;*#(2mO=3+_JK|ec6HMY-NLXmKtxP z-hQeRTa;TTE5q}@oW0?Kx63`PlX{bA7%IamoSaeDtzDdWb{39A1R?c0Q4!C|3=4E7 zAIDiWbPK2H!9<3r#Ky(~f$rcyqST7jYcD1}#G6bkP-s|5tym@YQ!~ixdS*Ne8*6JD z3mZ0N4dN`B@X#|efz5Fc1eu2^6}-mR`Xy+c5Y1@-J#go zz#pd6BM_UJSw#))+zy30t3gUVDLp+SLr~t*PPZ`~3Jnqcl=^s5T1I+CPHh{F7gai1 zEAle!da3Dg$*F0n8AXk)ZEfxCZ5TmIfkMQ$ zPo|LtWn>zuHjW~cn3z*Xw@|G#-quu>lg$xK&+(l_hLVx7nOV7T{30@xR1b@fPmGVr zsKfT3ZdGZk&CANp<_Z+j9msIfFF85AN+@ivFOd%?CxxTWic#MIOhA=9ngTA4zIl+*c9q>D(+DXPI46!ymT1$3q&S~xnJ5vb?J9=Q>a zn3C7Q?N+WxOCrO{8QzgGQDO0g*h^PtmteD2o|VqYoR%#RBIIJ}E`(~v1gAjl#E%r$6ef_=kFYwK!ji?b>ltCJ(5!(+jpw8{;c`@bYZOzlgV z#ksjjnH9|)-4*bYjLd8}V19uh9z)DG(4vM!gvaJo*49-Zl~Ym6C#0s*X`f`| zS6I#=bIk7#o%bxt$<0d2scx-KPs0kbKq4={xFkb$tPsL<%dgrvC8kQj8_se(Kgj55um;$o6A>Om_vC&Du< zJ{1+Mw7xVY4ukS?rOLuYOfqLW-SPAf3{A=^sj8|h$}cKNN2@`{tE1A#$AD@Aoi?d7 z`?xL>6dRLT-Bim6-pol4^o>YL&n#ZlJ|mcwBS`k)$EM_UX8-#AVazjc zL>HBz23F>hdFDG-E*@Tf;eztAiqeea{HludP+#BB=$Pox5PoP}A}5(nnUt1aUzrA~ zZ4J2y%vm`J0ig+1Ew_GpGS5saBQ>U`B$~`K-!gOc@b-_*FDolA&q_+p%#RBX^$!RO zi;j&A52ItKL?(G^BDRTXIW-N{b=9RgB-Y=~D~a=qs*XMVbfy_DuhDg7+3ZYH&B58j z+b^-Wgeg-3N+5v_ry}UkiT)wzCu5>QA`+A6DhTXnGEv5+xf-OA%*^S zPbZsUwGa{&xxOZ!oor6fbK<#s`uW8dm(Zo}l~)wT2lxhsg+~Mj`iG(&3=0m4OvFAu zIUzg_Wa)G|Q#m^evBwd-lT(r(niT2v$FLK}+-&>W(p1C_JKr*~b$0WMPw??eEh&K_ z1d$>B9zNLpMFjIB>6ka8BBRNUJ~=rtCLZygo{pH!gd1jMaRu+@mSjXmM?Rf?vZTr0 zsim!@oJ>DGsM$7l&aR&E1$mJ^!PzCHMM=SYzMqG0XlOWL5D*d-8ygc57Rw~5B*ewU zr$KZ@Q0GGM83kntF_}^FF(`tbsDo)#YiVz(l8-?@GqbYgxp{bm<`iZJ`9u`tMg{}~ z@&o*kXu_cxUmyPncyA0pD27f_PLAP+C(~(khGJ%R77dM0FUShdEX_}hj?S!W0CjYM zoJO_gw$_F`b|m_tp{1Sko!BT3&)CAE6kornVE=%?z@XqDUw=M7EQ0SJ7#u;zPKpT& ziAFD;6dw_hK&L7rKr=GwECu2xYWZbR;dynfEp)w#+?x7?L3_P?L^@-$p@prpUs}E( z#KSwas36+M&yV(>78nEtd3s~l92OoO85N5i*W{S6P-219#E9q=Br7Ga0*d-V?sP+JN(@AK-!n%uNue?_VWt~rNfnR z+z=5?$0|c_i0q`P@u6YK#3|V_Oje*#knigefiaxi!Rs508daOyo3q(Ts`^bMOFNHv zz%=N*3GtpDfj*vI-hRFeIA94u0pKtz0=^W0V2Tb6g_hu+_yg&XxDcI5XVU_W+=?`N z_lR`NypRN81d~RU_Uat@fORw1(83`gjmen+FiB3BhX)wYK5zT^!4hEMX|A>MTr`&s|k7b4{$A!ZT^X zBm$Pni}wNt!eX|spRZqFAfNB=@9RyRDU=@=is+4v4-Z6~B`2pOM#rYWS6>GkL>UfQ zO6kjvezAgL`BntWz`Q;&1nnfovZ}W@Cf2SASxmMn_+*8-yVD-ZVC3V&_$mYh(m~3> zA%R3+Z$w5$goI&NhC~q)hvTF;%mZPM3}|a+R(5_vnc;DL@35q-Vz$F?XfSS6Z|^-Ue3GZH=Q`E-_Yil37+k9Jj+^YWy!L7 ze~f^q@4a!`z{1ihFg*i#CpI(6)rodi;<>oE(e5f9o_DZ3#`hI}f8+r^-`B$nc_1<@ zG%7M8CYFwWH!?CIDJd>8K82hpHRR|WJ;Ct`iAgIcE+Z#5b#y(|V9+?Rsb?SxyFdAS zc>1~Pw~d^_+^ifTGctng-29y!X(xt9xzcW`a(+Iv?+iablGu3C=v%J27m^U~*p1 zO$+t)4}d%IgMtE4&T%Rh>K_yl&BV@%Pe?AWzw^_N=WYE%qm#1ou-=NwO7uN7wM_kt zTK0gfdnnZqT%V4pXPkFRL@SyMcS!KIGPkm_wy~jYDSO&c1xF$-AsKWQg^k26CW zKj=Crh#ws2#}5f1hjF2PNTN87ORFt3IDGhub0CJEf;@C?@Ln=*BExrN0{p6PA1*X{ zZiKCR_-Y_&Kj>uj2%fpQg{7qxIMd*)?9B5>KtZIlCkQeyM9obM@C%>==LGQsJiUAa z!XwCvgAuB+*)=Iw4*#U*5*VGF0mNQTeldFx2&T2wwVe8CI8th~uy}5=t@x{D9G$3w zra8dYoVK7Xm94C7Y@z8_9UPr_{web0oE0Aw5S^8m9f|5XHvoYf;P1~TjLDH)Y+ON& z-?2l#T6hIV0V$YQkY9k|Hyf{DTvfxV*Jv8(bq9>$nYs70y61?@^;S|%q;Bhk;((>p#lFEvOWzI3n(j*8J%G0_W?%JWSR9YMhei%Uq$#?%@| zfjA&S3_-;}IIx=TBV(**C*l)NF%dX(OANI)HKolI%qN8S7MaaOYPLzV-E; z7!5o>E}wGJHYOn<&fDC?#MIQ>j5b%dfQfO6U<(^7xdue0a59%?CHQ)Hc*W)92%>!b z{Qdk%iVX1eMjS^(JqPMGW6V;j_?>{p~ zpSbsocS1shqp^vR32mxwW^M*mTUsHYCfV59+XtalA$w0cOFi1pKO#LBdq>7k5nUS1 z|Af@I@VJtEvmbsqZ{vjlAJ!|##g@3Zs0fi%T~k#7AW$6x`vRuIB0c^bv>&|{9`9#C z8!4E8?`vje#KhpsuGrq*FDadDE$K{^tjx63Ok@z{!~m?B33wmJ$3oOq zcr#P`N)2Ywb@g4tX&mVInW6oA*X%ilj1h&EDq^Ly#Uw@Cmu^%srey6rluyR5Ir(k zDgr^AFRAJ8`1=JUR|NmO|0hhoB6F%6J3HE&YYPSJDQsyOQ?7_JRZgu+U44JIr@=Fr z01WV#UNdG46=5@m*bI?54JNa)=aW1f8kj%@%-nqA z%Uip8`-U(i?W;rXK|GdWqYNK`lhC!wb;5yI!{-45O6vQtCM?a!*oZNq%(&*$E$sZ` zlT(rd9Ya%7($kZZi5}<0BOH-|e7t>w^HVPF`~H%RM?hRvJDG704PzuLZ7V|BK@cJq zs;jChs_0scj=>y*zXK7xqhrZ2q>LEjBc^ajb8~wScRt#xFi)4D7#upJ#|K3uBqcP?ftHB{ z(WMb|`6k#|`NkzABx7NB!Xw>modRR{E<8`KJB-`s?xd;pPc3xXx9^0pi+5mX7N%Pm zw+{}sRW}XZ`)#b9jHTGJMb}KPt!)?(x**7(!5Jv29k(?hOQTIx%d(e_4+A#F6n#Do_e6Nxp2x;q6$xsYN-+Al|Ew0thK+b8bfg;BqJ zbLhH*2dZ*-OhtRAu)A+?pb9QuJaqrz{ay?aNHo_>tF7rA!ff(6NWwQZR*a#Vk&&T^ ziEVg1ouKM#?-d&2gmkGyN(AkoguVw$`qa%Mq1bKz-edYabd;FR##MH734x~=sK>CP zN^<|l*gk(k6s5TE_3iLcsVbW)j+pr)`^|YFX!8Tj{=b#Hpi;bL3 zXhRJn3oo4Q#0NV$28TJClPIQblwcw>a94-OYU}PB7)16pk*vdQw(t z`!4~(c6N@;SwW<%L`J2Q6Bcl648!mJ24DwRphx0VPwnhaVvvWPfi}E) z$<=~3oM7x77wu;47vW(^o2gh>SRtv?))aL0g@c3Ros<;4ulD?E%Ddx>rW<>vh{%L0 z*aSR=3DiN(<9-KLF|}ndkNX_bLFo%q59mqVBh=EYch}IC^Kq zoZh+rvbBq+A9l`U5s^`e)$MG+3OdPpXcHGN zOPWnNi!9_t3DiS#T=wofc-zL+i|kT@aL5}DctvJyCx8`zMiLkVfmJ;2uB>8UgMQ&1 zv*%$D6R!9n#VC+OO`9r_eu}Z2i{91N#w9V`V8`yC4IErNeXt)1;)f8;V2+yG1_KWf z1nd}#*^pK;Rnw}gg?-VS=dlrUZN0dLO2)<}CLGhn^2QX!)W$s{@$9xeXG|R3JbloB zKcO5Aj7eEXFDMh7{$1Gh!AMgj4a!w*0~w6{pKu9pO7T0sGY6T<5K^llGolZ)Ko|H$ zP_Fm)JHEYQ;pFa#jc|Z}06#bso5a}Midx{z+WTS75eaTHjPyX)RZ|-WtBovhNbo0o zViLo*=w=NhgsHa0>7XF|wYSlA~doZr3o7kwKiS5GfF)gS~Z znei94cXqdAGzn`u#o~sdViej6x^h}oRZnjynulkR6~{u{NMfT+mXP8A!rqy8zWe%n z9TOX8*E?S9Q2>;S?gR*lxaXA!$Op>Ky~A^z$H#35H=-&;eBY z3JR*JZAhZomc1u+&2Ub6$IAx?=l*lhUBZhaV&co%I+}ATI_glWNgK@;G^DP^!D55w z!4_-WgUsYaH<+5)#zY@mp{c_)vvYDKr%F&NIZ`5mCgxYPbaWIHcGQsSPbxC$R3U2J zK(h@R@@Fs?r$SvBww+n#p60%D&IhZ{8QVFyx`7_LL3uDhMnOYMTSs+9YZERa$yrk{adgi}g~!voQL%rJ6E5Bm1=DNpbh-&+Oxp)um&ioe+Ponvee z)(b~RLme8PSdJSt1=+1t*gME=0&=iPbzeIG=Fi|Sw#+yl6p!Q0Q}bp%i@!K%A0LiQ z7&)~;c8V=;X)VicY$Tl|5spY~f1Gz^v*y$FBtopAyNMhJoElIE7&+@?YtJi~Ta4tj7Xr>3vX@x}Oy z@3}E)VNfhkr4{KlmDrPkvE12-V!M0z%nR`s`}E?nqQfGh5;6SC#e9ry$HA6ed+R{_ zO{B9I;4iMl6~qEk7RTa;z!Fn6xz5TOhjQtc;4iL56{Y~jgcERfnNPy9w5(>h!Te?T zi_m~S$lh(y;)vU#vhl=%qM0^qc;%CeJuBNJz zvX-Gb%a`FVEJ`|id-@0Ka18lk`~?$Q+SVelz4}u8#SIIK8~?#ytXjNu+4>zDfWP?g zv%k$MnFVL$K}AAB}%-S$1#(1R*kUfTxz#mtXCU9x%G zA+821>qn_c^V z*t28zjzzb4zG0>HoCdX`NOS?7Ec9a5JD;r3-m7DZ0|HZyp{3E$Z8SbMZTt2;r!QW* zdPC={-D?indS%yf8YYxRp~u4*({!(Zn(_9#pRe6|SeJ{w4Ij0*`R$f1^ww9lZQHu_ zFs*xFtM&ozwcR_{UJS#XN4jBBRV>-2pp%PmBEX9o@4Po(Yu80XQ*#qz>rx7MYk{K_2mt7+a$IZDHPM`XE$By;( zY3Xcf1S~fWz=fpLq~v%Wxjp{ctPhrLIz$`m>l>53>$R`7u?X$Co3}s`{QmarW&*h| z_wzBkasI%L9b3P`DO3>I&qOBX78jQa($dq?l0r;kscEmz`fSzKlN>`6?u}b|MnuP@x<(neFc4EOfI4I4ITYj47DEREVqZ~1)d>C@YEZ@GK>ge4oD+YYbax$c<# zoxsrW^vbB4Cr_La`n}_pDzJ@tBPY+7OS~tg&S?OmObP*^}Sx z-m)Fh&Fpx4_uiizeDZ^Sc>=UJ&(F_6n_rNZl_&>VOrQDoLd_rbxQxCkef#DyZ7nTk zJ+n!9<0crEqph%cE3-vq+pe7(wYD3pisfogWMdWHy>06@edu)Nw}(yz#s%83 zm&+>)S-OREky>e0MP4Fqm%CA~Oq(%#>8cgGujyUXUiJ0$%eyr-*J!SzwUpOuK^gQW zW~1V!&0834B@#EBEy^SdAyMk@n10{~^Eg3jbVOuoc}adA9^O#M0pW^@;xraf@y66? zuYJDe@OLX#9@3+auU-AM_L|jeG$A&KtF2qV0a}JXY*HXWNg)6fk!0vCs-REw4f=bJ z|LT=oTvJ(EQh>)xfP5jhNDUL};v|gOohXf|8nfnUpT2Q*_lmWr^ltB8MX#pTFq$*h z$?dpaYdvhaX%h(uc!x6Fjbu?~8wYBc_Vq7^Z37bWii+~sPPm}Zph&H_qB1W6*Uud& zl_?q@EZujRzM+14P-s-7T3S^Kv2i2)4V5V~Kh-*>d;R*2n>T-4y+T`a<*Jpd z*Q{B+nxjdtQ-jji6N@5HhzF`|Mi`T9#evT09n-!#bLs~x??}wd2uKYo0qNqZyktP0 zZ7J0WQ{J4n^PDboUG3&g-90N-tX#>gQdqs3hTs#m))T!T2seSY5|Le=QsIUmJ!8j? zJ(n+UJLcdUm4aOtc@#&XF|=Kq7E8br)|A?$sUIx+{<1EJE8VzpY%RTlTFF_ZPArQ5 zwARtNI=jz+(mBEZM$_j+S`n9l8onSJe6L(xT-ER@Ck52ed6>_ zHGjFv=+f7fF7I8roLQl;awQGjb2OER;yGFh8;Hwngl3fCkHlf#U>$PX_WgRCZR;*O zdWFPc#72S=@~f9N71+BIw1fqvu0G+7c}rIPa`hUct9JdA_OfNmS1hMj&?}WzuU@r= ztEsRS$TR>TIxuIB*kn*N#kh0{fCma zpR+ixx#5iMo#5D%^sGz*AS7$3=oFAEa|9nTT}@r%lNCQ-KC^N0o~zfco!zo@DZNZ# zIrK!YR3LnqH7c5#>kt8q7H5MJ65}R)Vu~%VZr!^3y2TGmx1O`T!;eWy0~D7WpcofT zEbXYbagg7MH=#6CRbQRAaN#$XF8{Q2+0m;61H?G&h zI@WJw^BG551=*K$2U}j-`kk@f=2hQbb-05Yw7CDt?oSH}4T~n0GqNxXsC zmQyAdwX_b?Eg#*i(#mtgvOP4NN3P01_b?BF~r;i`lvW|fg zC$C+*VLf4o97qy3S9{jx&EFc_)?TsalBHWfcx+;7W;&L|I&mRgKov4Ylgm2ltqh)m z9SkWIl{eQO(*ZlR)7lG{YcE-}h+eF)1nbj)U#~lI`I@foHQj6H4r#MyQv^ef76o1^ z#PhUK(_cGja%KIR?{3<<_=LnJrC=C`K^%O7DO3bsx@dAqYv&zuw*3U;prZ8Z=3jMm zI2V+DTDD*Ty@<0|f2pG8Pgm({99_k0r?wOCP*}H)L25*J(i`6a7j5lrS8R_h-te=b z^Bw=N*u+FKrxf77{CuWxMnOKVa}+fRqj1Rh2dF_wZROc>G*RQ}-HR72Sh$e0NOAF! zCCpOA72jN>uTt0abrnu;rB{3h$g14qRRN44nrN(&c~#VIY8^VB+Vh47?x)pX8X z)zv+w#imjf6t4~Iu~0=Qliu|D5#t*hR(*5X(gimcfeubcPQxA_DTppm$S>d&PAe)G zmK))=`!kpH6&1fcO`liR(K)++88e@=PB9P!>p$_ytir7IqMTk*Z;_|clQg4j3GEXb|lNDrGmVCPN7CgXNv=zExCL^XU2X0?tAj?39*%b>RxUxHR;<)KqN{s+JqbQdO?s^|TjuEX z?{C=n^)2o33 z^gL$1!h!|NLIvWZ^b*CTJI`~kPCm2}x$)b}x)*jK<{8b8u|NdHIxKU;e){_Q6?-pP zI(r3#gh%512Ofx$jnGbLl#*z506Vmwk2K%--E600)39vKNDDvWXxrN`7H^MeUuw+-I-}#+1^s z)7o>na}?&zrRQ+s<#qVy3G-9SSMS%g zaJu6c6ihe~>?a_y>6=SNE`$e4NWN0C4MVc3$wYF z&pu&b=9l_&6z9$bFM8h8`SVF?S+HQ^?v1;Cz5q^~tIRc}bK6J>rPsWzskxiO*|c=W zuZA`*{^0;|N0VdBcsK^m2K@i)R?cQC&yQy3R}QoLp|c zNorOQ{a7UgTdY+OP5rq%Cn zJZ*Sr;kqNYEgggNYMa|}?SEjXs{~**9IdiGK<6ps=h6Af1x;PSVD#s+3M?qa50}j2 z&UqV3n?u$^ls13)w`VV1ys&TCcb6_)#*J7oQ~7y4>2l~*AFSSd{nn<%+fV6RI|mij zH?`qGQvG-U%TQga{6sbr?z&I9_m@3!K+&9=IYORZSGv{)2C0I zyKv!0?KKCEYb|7J$&w`oODU{j_P6?1)-K(B&d3_0uRFfEcu-1fhftW0_{`|L_uyWe zJQHy9r`8J-Z$FPP_-w}tR#mHxGZ$3%YVQ2;@M<`;!eV4`F694o`RWtq#}}{pj*RMD z-95bm^6{jQ_D-R&6w#75go&!S1mfdRfX-K~=q@z)J79s*itS4|bKYFAX#V$Q#?T|1vaHKG=wL0kISvSmAO zUe{W(^R$7bBhSU1Kz@Bws+-$7gg{~p3I}Arf&Tq^1Y@2?L3^7Airlk+g3rFvV&+U= zcu?oU+1)F5o;bLI4H8s4P)9pPFa7ifgP#|#`u2*6m4mYjP%J>`gy+@}`hWqEC%QpN zkAG_*^rzN$M%+R=c?L`{N$aa+^qdLv_UWA6x_tlfor{@y6r@)o`e7D-zI5q2om*co zSbyY}nGFUHt}J3cxB!nvff0HMmS7ZP?MILA)e-WQ!qnT(BMDyJxqAUUM{U=!Et&@p zubRV|r%pnAK2blRzV+Jm4GXuP;+osSv0aGt-aa9CVjGkX|w|Kcn|{pNU??F4UMACCMT2Ukpv1_hv1(ip`(R@%D>P&!|a_0cQmrF zbpVjV#ns&d`o<(MskV(MgeV+OeR%YEC>QQBwYfd`_Vf6Gw+?(`D6e@8dZf7v7c5+~ zNtf21xAEvLW6%UqR!%@!gM#^jh9^W>P{@68MGl=iEibP|7=QD5?7)JP+N3BfB}o+7 zjV(RtMxT2iH zE=T_C%r=~R&vExi~tvp-6BWdCm#xDhM^;O7mNr-B5&|c{ao3Z_aEq zm@{+f;oAp4oH28O_U;=t=9Yk60YyYR&*Bje_w~!bWtyV+lKN!yC`mxc%4M6<(80g; z96aE&lRqxz&RMYHJgq%zA`1@q#t1jp31o=1gsYo(B%WweRa2T+SeuQ;n@nIys|eYq zR(2&Lef;rk27m*W=^UDm?5C}Faq+84Pp|>|O+1_dJ$nbv;_Bw^?wt%IMRjFdHX%nE zLNqrhX&_hHRiytsHelk;o2S+;Tzf?K$j2JgAJ~9>Rw1rfEXj(l?yy5HFvRKcbp@zj zWUkD1F|ccXN4?$i*Z|d4=XH;tJiFmd)n~B*-&=)y6SNwU&eJm>r>a^IS5XlY9T$fQ zFfjz#1?RN1`7_U915`fQ_4V3Mrz<><4X_CJmuCdez__f^s@$03sw7#?9@X-w4-42WK@&L>xraU*QFb`84wr?kmF4075 zn-~3JXuz$AB!3`Pf)m0clh_uSwFo|n&(;XTu0IP6_~^MuGh7bO3aCYR11^VTM*tc|zzoqbau0xxa7nhW%TYsIPxWGGz!`o?8X%J}2f-B(I0D+s)(-#cFM|f0<(Fh(EBP#=x}F%_mqG))OAF%U zs+Thx5)UzdX| z6?tn@cf|FVK?5ucnhJ2;Dl@yPHw%!C7efOq1g%y1nSz?$Qd6UsJet9@psf=q*m67a zT#pw$nt=%}ZmLhWxbkvnfSK9#OaK3PG{dE3XMUxqwd&;Q@c;Sxj|Tpuf&XaWKN|S| ztOgYD^?ytFg;t4$SfiIF@O8tpizokn zU^9EB+P}#KUNw>aJ^S(T;bZS>sQg<5n4kIIx#N|}?Qcz1BFRYOfaR41YX2%rC>&`2 zOZMaAk@H`hsHFJut@yUz?hT|Io$)VmhndE*7qB0{Z~5`e2_KmhJs@v*e82d>D@y-# z5$2`6h&x^v{q*4*rUiezL1g%@%0Jf%O5e5qLH)1(QM>DA>f=9uAoKdKDgR6XUbDRW zC-J}hSAODe&%XXBd&|s!o(Y!cK1=)gfB%jPa(Ly@-wRlG_Kkm%026*?i{0~VpM3ZG z1N;w)WDo!9XMKk6|5KdcEmzj9|BA)<@4pEP;v$nr9{tr%N5dBU6P#du)nCzm^4f#8 za7#l@LDleIzbAk1^#7$7s-N!tYtrnize~by{JhtGWg7g1*U zKdRIDdd(F^J{t!vA@Lw7&R-gysCxztcXN=Jm4Fa6fDv>jeJ?LQJ_l@N)L! zkJ9)5knNoJm+$(We373NeWd~B|8xHD2eBXjOX5#o?7f)dlJJ+#|ME2)c{PEauPkX2MH#Rp(Y(Af&_&<|i8YB5Dvj6S1-(_R} z?KQmc``wP>q_Fs^!F#N7ev4i`UG;w=!F$1fMfD$l?QwUq#o2wwY-`5k@$-A`;h7T= ziT|Js-@eSF{}CzfS2!G6zjEcaVA+%0`Ka^uhtr7w|3EgFM*m~Fe~BRX1p3I5|P(1jeChs3) z&A#pTq2S}Im+a;hKijfBsyhDGWM##dI>Bp}f9cQv6W($GL^%$Y(G}w7KKT29)n_k{ zgT?93ec*rb&F>E-J-vSz|0yBqjoBJ6&P8gc`=7q?U-fs_&+lodzQ6(AaJc`kV*3Z( z--B1aJLRwW&rSQ|UH`&=6z}HiGW4_Hwvy(!%pQrRS4&~Gq{(Gk@-dr557*-OqqF3l}mDZLbng8?7s)`U3c|msg zh^^vwBxzbR|2*H)l3=eQ$_Z=%KtV9QvOUmme?RW)&hpff;9+Hk+0WENYd<5*|M&Im zlze|fDFF^<_=vp%9b^B;%_YUb=JGRZz=98! z_81tL-Ea@u5Hyk$1%E#s>`wR8k>X=xLz*XIWU-)+|NnizI4#rLNKTLwXg$LFjI6fD z=u-3kyt$;v-$Y)BiybNLF)%W6I!r?CoRJcy#H;=DWPN3nrIHw^*hlytXg`}#>K@v6 zcm96d+nVI8Cdvyccu?$TQ3|iVL+cp$_w8g~s=KZP4+k5H^+5kKbDJj3qIjHxKt%kw zHap8*PllHh&3Xn#CT3PK&zu9aEdqZ(Tv;A$A}7ef4xAl>H9EjFBO?;_qdvn^XJL(91mS7K6b20AMOmG1K4?VliHqAIS>5(u&p#eUxpvG&V^eGX8>yfRt|o< zY%0gVzpp17gN@|`I8hp0a9fcWpcvqi2`oK>bqa@+5Jy(~ZB^l4J!B0ti#}fV?f9@dnNTo|Ng$+kn5=_Nhs|>odPa}q=Snu zP^%F5`}shHkG>Q?7p`&-EeybUKqs*sOAP$`O?s^S`+lxH*g!^r8>7lcvlqsNX(tJ4UTLVX!%9BXMevtJ0;oG z(Qm@#C*Qy`xP(IjaOLR{F|dvLq3GJp=?5Om6$_2T!xe}8{}y1P8zRbNY6-`F;6`sJse zi41|iA2*~qsEPn{9x0Izb`K~Ma><4iPQUs2>&KTTCMR0ys3|I_X&74j^q;)Q~)Y? zytO63X%A}{;}--c0kyEa(yGctdwq2UX>nm85pfw69TV5mefNoQ!0)@WLQP~yPkXQc z0A)fxc}s6UCp`^ic_~pLJ{}%^5h*1tQ^%a0_h0=akP832Ss81gAjnO6+JiX&*dyfR z6_%8dlarH?5aH+H;^5%m5t2~WFtkb7aP8?2ybk#LXVr8#@Ol2L~G~xZw&8 z57r5c@a-eWHa{(jh!Vh-$Plb!b9?gK8NWdZ^Cx_*!YIC#aRm32(qn)cp#{}W3=@bBy4 z0vlyfKG5hY+$3@tpjEs;0M`y4sNfNjQqneaFWh>4{jd@1Ly!? zCq+n7QOndme#7;r-_TRxpNG@@b;W@N4;6fmVLMO&>;P^-2?bz5kht{9qpzqA`1^iM zw27=Bu+l>cHEiaPF9r+&Hf{lNU_oFVJLCL=PsrKe-7h99k_V&&e=6N zwki}>dPG|fR0t}GfCYh~hLLqp(WJ%8CM1}vNej{;@?nky6$D%YVsfgwCic#Lfew1g z65vV?CQox3ToCYyN-JsT=;`Td$OEmXVY!FJJKzc#cyg|cf|8Pgw3q;G%RL+p;NS+f z(!|AqO;j?vI#|pkNeGk;*f_X(`S^e>R4fDgBpF7IVxR+q zy!p+WZilbWjCwSsF%`7JI>S1^*%Ifk^h9m?passCxSmr+Ch~QL?`L#`SIfRLNbBIjlSO+w*>xw#do!L*eWh0s`sHAB1puprIN`^%1&{8(5T_Nucm61GE z%|&gWUT7Ue=k(&3e%CYbU$PIWt0>3$R_VIB#*(IT`g)Eug!3BRvPOrddg>fKrjuY- zE6p@sr^#Jp?42b9F}$hHI_(tRG}^kiypu3*2<@%i1=rYxiX?|qXnoCiW~V9c&OCxx z<`kEmevHGKIi9%gux1V+=I71G?)v%8T=q5NnO&8|<xM4D#4}id z>4Yb>A)Xgn@zGwHCQWHfD2h6Y%rni(!m5AiDi*eivP3bY@b zlYZmLbw&5^h^Ogh&xKz{G1gg$V^pNjjQY^!UMW>Id6u5qT`n}EDvEYR#|h2n0==2j zIgZ?Raf!^Dv#7d9D%7Pr^r;`k;J%n3I#2BK4~28$ouIjIAMmSZ9CLcddmG0HHQM06 YM~G|gj`5?IpEye!$5os?ba6SqZ;~tQ?f?J) literal 0 HcmV?d00001 diff --git a/krb5-1-7/src/kim/agent/mac/resources/Remove.tiff b/krb5-1-7/src/kim/agent/mac/resources/Remove.tiff new file mode 100644 index 0000000000000000000000000000000000000000..dacc97c3e995cc829637225feae7247ec5433fe9 GIT binary patch literal 694 zcmebEWzb?^VEoX)px_uGz{JVibnwB287WG#-0g=J1>9%}Qx|M%?Vq^)=Qmr~{^R|d zI3<7i{GTkpRH)KtU8wF1ZvsJ5BMtk4L*|yqr+s*uqmvY6qV~@Se+a0^E zeD>OJAM18s&adEp`k%LPZ@9sZ9yN1*pM#G--Z(Q&UU^FW z!S`JHW|u!l>z=*2VSjhG?X=5jZ*RRb`}vpCxOS=P{*yL#;==9+?+csH>TTZm|LpTO zRkFPIo#Qv&{Z@8&@Acy1`)|w3W$mU^1m?sKj8Q4S-B(oAAxem03UI-gA;00*_|fzXmdCV%+cjNY_RKDg$w&1hYFWK z9(SQ56Kz6;T_^fPi?|8K#7Z7Bta?^)oc&Kh#qq#1<#NX-{%Mu>n8eeq;3*{2t9sJN z>RF{1`=14sUO_#}wN6divsK%B(wW^lK0yAmQIG*B57f)Rz`-aA z6$gqiiowJgOBluB?B|S93_ue=>Y0`?O2gUf7-gV(fijF5NahD2#DV&Nwm>1*p9Tg7 JbpZw_4FG|-{1X5G literal 0 HcmV?d00001 diff --git a/krb5-1-7/src/kim/agent/mac/resources/Remove_Pressed.tiff b/krb5-1-7/src/kim/agent/mac/resources/Remove_Pressed.tiff new file mode 100644 index 0000000000000000000000000000000000000000..de3f877911039bd5f5e95f4acbcbd6b5218514ed GIT binary patch literal 656 zcmebEWzb?^U_8~ppx_uGz{JVibnwB287WG#-0g=J1>9%}Qx|M%?Vq^)=Qmr~{^R|d zI3<7i{GTkpRH)KtU8wF1ZvsJ5BMtk4L*|yqr+s*uqmvY6qV~@Se+a0^E zeD>OJAM18s&adEp`k%LPZ@9sZ9yN1*pM#G--Z(Q&UU^FW z!S`JHW|u!l>z*yWVgHRQcG~gut+#T&y#JK;-OIavQbmlMTz}(Uwe&C6b!oTf?tFf2 z^_+X{;f2>d8$tb2Uy)YFVp!>eH01TBn8HY}Z*=%(c@{*I0R}(V1eOi>7Bj=bSY^8(g$w zuHWP}Z>`S@pZRKge)6fN1q&1y_!t=&m>GbP$sh(K7?IdaU^WW_15*VfGgO=vsD=&7 zW&*MW8G!OYy$lQ-jG|C+pa`QFOq{WVQ5?=b#3;o8Gy$ZZsew@%&hB88f$9ayFlr!~ XAA}GG>I2#Wg +#include +#include "kim_private.h" + +struct kim_ccache_iterator_opaque { + krb5_context context; + krb5_cccol_cursor cursor; + kim_boolean first; +}; + +struct kim_ccache_iterator_opaque kim_ccache_iterator_initializer = { NULL, NULL, 1 }; + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_iterator_create (kim_ccache_iterator *out_ccache_iterator) +{ + kim_error err = kim_library_init (); + kim_ccache_iterator ccache_iterator = NULL; + + if (!err && !out_ccache_iterator) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + ccache_iterator = malloc (sizeof (*ccache_iterator)); + if (ccache_iterator) { + *ccache_iterator = kim_ccache_iterator_initializer; + } else { + err = KIM_OUT_OF_MEMORY_ERR; + } + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&ccache_iterator->context)); + } + + if (!err) { + err = krb5_error (ccache_iterator->context, + krb5_cccol_cursor_new (ccache_iterator->context, + &ccache_iterator->cursor)); + } + + if (!err) { + *out_ccache_iterator = ccache_iterator; + ccache_iterator = NULL; + } + + kim_ccache_iterator_free (&ccache_iterator); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_iterator_next (kim_ccache_iterator in_ccache_iterator, + kim_ccache *out_ccache) +{ + kim_error err = KIM_NO_ERROR; + krb5_ccache ccache = NULL; + + if (!err && !in_ccache_iterator) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_cccol_cursor_next (in_ccache_iterator->context, + in_ccache_iterator->cursor, + &ccache); + if (err == KRB5_CC_END) { + ccache = NULL; /* out of ccaches */ + err = KIM_NO_ERROR; + } + } + + if (!err && ccache && in_ccache_iterator->first) { + krb5_principal principal = NULL; + + /* krb5 API is sneaky and returns a single empty ccache if the + * cache collection is empty. Check for it: */ + err = krb5_error (in_ccache_iterator->context, + krb5_cc_get_principal (in_ccache_iterator->context, + ccache, + &principal)); + + if (err) { + krb5_cc_close (in_ccache_iterator->context, ccache); + ccache = NULL; + err = KIM_NO_ERROR; + } + + if (principal) { krb5_free_principal (in_ccache_iterator->context, + principal); } + } + + if (!err) { + in_ccache_iterator->first = 0; + + if (ccache) { + err = kim_ccache_create_from_krb5_ccache (out_ccache, + in_ccache_iterator->context, + ccache); + } else { + *out_ccache = NULL; /* no more ccaches */ + } + } + + if (ccache) { krb5_cc_close (in_ccache_iterator->context, ccache); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_ccache_iterator_free (kim_ccache_iterator *io_ccache_iterator) +{ + if (io_ccache_iterator && *io_ccache_iterator) { + if ((*io_ccache_iterator)->context) { + if ((*io_ccache_iterator)->cursor) { + krb5_cccol_cursor_free ((*io_ccache_iterator)->context, + &(*io_ccache_iterator)->cursor); + } + krb5_free_context ((*io_ccache_iterator)->context); + } + free (*io_ccache_iterator); + *io_ccache_iterator = NULL; + } +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +struct kim_ccache_opaque { + krb5_context context; + krb5_ccache ccache; +}; + +struct kim_ccache_opaque kim_ccache_initializer = { NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_ccache_create_resolve_name (kim_string *out_resolve_name, + kim_string in_name, + kim_string in_type) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !out_resolve_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_name ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_type ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_create_from_format (out_resolve_name, "%s:%s", + in_type, in_name); + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_ccache_allocate (kim_ccache *out_ccache) +{ + kim_error err = kim_library_init (); + kim_ccache ccache = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + ccache = malloc (sizeof (*ccache)); + if (!ccache) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *ccache = kim_ccache_initializer; + *out_ccache = ccache; + ccache = NULL; + } + + kim_ccache_free (&ccache); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_new (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options) +{ + return check_error (kim_ccache_create_new_with_password (out_ccache, + in_client_identity, + in_options, + NULL)); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_new_with_password (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options, + kim_string in_password) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_identity client_identity = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_create_new_with_password (&credential, + in_client_identity, + in_options, + in_password); + } + + if (!err) { + err = kim_credential_get_client_identity (credential, &client_identity); + } + + if (!err) { + err = kim_credential_store (credential, client_identity, out_ccache); + } + + kim_identity_free (&client_identity); + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_new_if_needed (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options) +{ + return check_error (kim_ccache_create_new_if_needed_with_password (out_ccache, + in_client_identity, + in_options, + NULL)); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_new_if_needed_with_password (kim_ccache *out_ccache, + kim_identity in_client_identity, + kim_options in_options, + kim_string in_password) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err && !out_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_credential_state state; + + err = kim_ccache_create_from_client_identity (&ccache, + in_client_identity); + + if (!err) { + err = kim_ccache_get_state (ccache, &state); + } + + if (!err && state != kim_credentials_state_valid) { + if (state == kim_credentials_state_needs_validation) { + err = kim_ccache_validate (ccache, in_options); + } else { + kim_ccache_free (&ccache); + ccache = NULL; + } + } + + if (!ccache) { + /* ccache does not already exist, create a new one */ + err = kim_ccache_create_new_with_password (&ccache, + in_client_identity, + in_options, + in_password); + } + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + kim_ccache_free (&ccache); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_client_identity (kim_ccache *out_ccache, + kim_identity in_client_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && in_client_identity) { + kim_ccache_iterator iterator = NULL; + kim_boolean found = FALSE; + + err = kim_ccache_iterator_create (&iterator); + + while (!err && !found) { + kim_ccache ccache = NULL; + kim_identity identity = NULL; + kim_comparison comparison; + + err = kim_ccache_iterator_next (iterator, &ccache); + + if (!err && !ccache) { + kim_string string = NULL; + + err = kim_identity_get_display_string (in_client_identity, + &string); + + if (!err) { + err = kim_error_set_message_for_code (KIM_NO_SUCH_PRINCIPAL_ERR, + string); + } + + kim_string_free (&string); + } + + if (!err) { + err = kim_ccache_get_client_identity (ccache, &identity); + } + + if (!err) { + err = kim_identity_compare (in_client_identity, identity, + &comparison); + } + + if (!err && kim_comparison_is_equal_to (comparison)) { + found = 1; + *out_ccache = ccache; + ccache = NULL; + } + + kim_identity_free (&identity); + kim_ccache_free (&ccache); + } + + kim_ccache_iterator_free (&iterator); + + } else if (!err) { + /* in_client_identity is NULL, get default ccache */ + err = kim_ccache_create_from_default (out_ccache); + } + + return check_error (err); +} + +#ifndef LEAN_CLIENT + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_keytab (kim_ccache *out_ccache, + kim_identity in_identity, + kim_options in_options, + kim_string in_keytab) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_identity client_identity = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_create_from_keytab (&credential, in_identity, + in_options, in_keytab); + } + + if (!err) { + err = kim_credential_get_client_identity (credential, &client_identity); + } + + if (!err) { + err = kim_credential_store (credential, client_identity, out_ccache); + } + + kim_identity_free (&client_identity); + kim_credential_free (&credential); + + return check_error (err); +} + +#endif /* LEAN_CLIENT */ + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_default (kim_ccache *out_ccache) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_allocate (&ccache); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&ccache->context)); + } + + if (!err) { + err = krb5_error (ccache->context, + krb5_cc_default (ccache->context, &ccache->ccache)); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + kim_ccache_free (&ccache); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_display_name (kim_ccache *out_ccache, + kim_string in_display_name) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err && !out_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_display_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_allocate (&ccache); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&ccache->context)); + } + + if (!err) { + err = krb5_error (ccache->context, + krb5_cc_resolve (ccache->context, in_display_name, + &ccache->ccache)); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + kim_ccache_free (&ccache); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_type_and_name (kim_ccache *out_ccache, + kim_string in_type, + kim_string in_name) +{ + kim_error err = KIM_NO_ERROR; + kim_string resolve_name = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_name ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_type ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_create_resolve_name (&resolve_name, in_name, in_type); + } + + if (!err) { + err = kim_ccache_create_from_display_name (out_ccache, resolve_name); + } + + kim_string_free (&resolve_name); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_create_from_krb5_ccache (kim_ccache *out_ccache, + krb5_context in_krb5_context, + krb5_ccache in_krb5_ccache) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !out_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_string type = krb5_cc_get_type (in_krb5_context, in_krb5_ccache); + kim_string name = krb5_cc_get_name (in_krb5_context, in_krb5_ccache); + + err = kim_ccache_create_from_type_and_name (out_ccache, type, name); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_copy (kim_ccache *out_ccache, + kim_ccache in_ccache) +{ + kim_error err = KIM_NO_ERROR; + kim_string name = NULL; + kim_string type = NULL; + + if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_name (in_ccache, &name); + } + + if (!err) { + err = kim_ccache_get_type (in_ccache, &type); + } + + if (!err) { + err = kim_ccache_create_from_type_and_name (out_ccache, type, name); + } + + kim_string_free (&name); + kim_string_free (&type); + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_compare (kim_ccache in_ccache, + kim_ccache in_compare_to_ccache, + kim_comparison *out_comparison) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_compare_to_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_comparison ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + const char *type = krb5_cc_get_type (in_ccache->context, + in_ccache->ccache); + const char *compare_to_type = krb5_cc_get_type (in_compare_to_ccache->context, + in_compare_to_ccache->ccache); + const char *name = krb5_cc_get_name (in_ccache->context, + in_ccache->ccache); + const char *compare_to_name = krb5_cc_get_name (in_compare_to_ccache->context, + in_compare_to_ccache->ccache); + + *out_comparison = strcmp (type, compare_to_type); + + if (*out_comparison == 0) { + *out_comparison = strcmp (name, compare_to_name); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_krb5_ccache (kim_ccache in_ccache, + krb5_context in_krb5_context, + krb5_ccache *out_krb5_ccache) +{ + kim_error err = KIM_NO_ERROR; + kim_string resolve_name = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_krb5_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_display_name (in_ccache, &resolve_name); + } + + if (!err) { + err = krb5_error (in_krb5_context, + krb5_cc_resolve (in_krb5_context, resolve_name, + out_krb5_ccache)); + } + + kim_string_free (&resolve_name); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_type (kim_ccache in_ccache, + kim_string *out_type) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_type ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_copy (out_type, krb5_cc_get_type (in_ccache->context, + in_ccache->ccache)); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_name (kim_ccache in_ccache, + kim_string *out_name) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_name ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_copy (out_name, krb5_cc_get_name (in_ccache->context, + in_ccache->ccache)); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_display_name (kim_ccache in_ccache, + kim_string *out_display_name) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_display_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_string type = krb5_cc_get_type (in_ccache->context, + in_ccache->ccache); + kim_string name = krb5_cc_get_name (in_ccache->context, + in_ccache->ccache); + + err = kim_ccache_create_resolve_name (out_display_name, name, type); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_client_identity (kim_ccache in_ccache, + kim_identity *out_client_identity) +{ + kim_error err = KIM_NO_ERROR; + krb5_principal principal = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_error (in_ccache->context, + krb5_cc_get_principal (in_ccache->context, + in_ccache->ccache, + &principal)); + } + + if (!err) { + err = kim_identity_create_from_krb5_principal (out_client_identity, + in_ccache->context, + principal); + } + + if (principal) { krb5_free_principal (in_ccache->context, principal); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_ccache_get_dominant_credential (kim_ccache in_ccache, + kim_credential_state *out_state, + kim_boolean *out_is_tgt, + kim_credential *out_credential) +{ + kim_error err = KIM_NO_ERROR; + kim_credential_iterator iterator = NULL; + kim_boolean out_of_credentials = FALSE; + kim_boolean found_valid_tgt = FALSE; + kim_boolean dominant_is_tgt = FALSE; + kim_credential_state dominant_state = kim_credentials_state_valid; + kim_credential dominant_credential = NULL; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_iterator_create (&iterator, in_ccache); + } + + while (!err && !out_of_credentials && !found_valid_tgt) { + kim_credential credential = NULL; + + err = kim_credential_iterator_next (iterator, &credential); + + if (!err && !credential) { + out_of_credentials = TRUE; + + } else if (!err) { + kim_credential_state state = kim_credentials_state_valid; + kim_boolean is_tgt = FALSE; + + err = kim_credential_get_state (credential, &state); + + if (!err) { + kim_identity service_identity = NULL; + + err = kim_credential_get_service_identity (credential, + &service_identity); + + if (!err) { + err = kim_identity_is_tgt_service (service_identity, &is_tgt); + } + + kim_identity_free (&service_identity); + } + + if (!err) { + /* There are three cases where we replace: + * 1) We don't have a dominant yet + * 2) This is a tgt and dominant isn't + * 3) Both are tgts but this is valid and dominant isn't */ + + if ((!dominant_credential) /* 1 */ || + (is_tgt && !dominant_is_tgt) /* 2 */ || + (is_tgt && dominant_is_tgt && /* 3 */ + state == kim_credentials_state_valid && + dominant_state != kim_credentials_state_valid)) { + /* replace */ + kim_credential_free (&dominant_credential); + + dominant_credential = credential; + credential = NULL; /* take ownership */ + + dominant_is_tgt = is_tgt; + dominant_state = state; + } + + if (dominant_is_tgt && + dominant_state == kim_credentials_state_valid) { + /* Since we will never replace a valid tgt, stop here */ + found_valid_tgt = TRUE; + } + } + } + + kim_credential_free (&credential); + } + + if (!err && !dominant_credential) { + kim_identity identity = NULL; + kim_string identity_string = NULL; + + err = kim_ccache_get_client_identity (in_ccache, &identity); + + if (!err) { + err = kim_identity_get_display_string (identity, + &identity_string); + } + + if (!err) { + err = kim_error_set_message_for_code (KIM_NO_CREDENTIALS_ERR, + identity_string); + } + + kim_string_free (&identity_string); + kim_identity_free (&identity); + } + + if (!err) { + if (out_is_tgt) { + *out_is_tgt = dominant_is_tgt; + } + + if (out_state) { + *out_state = dominant_state; + } + + if (out_credential) { + *out_credential = dominant_credential; + dominant_credential = NULL; /* take ownership */ + } + } + + kim_credential_free (&dominant_credential); + kim_credential_iterator_free (&iterator); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_valid_credential (kim_ccache in_ccache, + kim_credential *out_credential) +{ + kim_error err = KIM_NO_ERROR; + kim_boolean is_tgt = FALSE; + kim_credential_state state = kim_credentials_state_valid; + kim_credential credential = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, + &state, &is_tgt, &credential); + } + + if (!err && state != kim_credentials_state_valid) { + kim_identity identity = NULL; + kim_string identity_string = NULL; + + err = kim_ccache_get_client_identity (in_ccache, &identity); + + if (!err) { + err = kim_identity_get_display_string (identity, + &identity_string); + } + + if (!err) { + if (state == kim_credentials_state_expired) { + err = kim_error_set_message_for_code (KIM_CREDENTIALS_EXPIRED_ERR, + identity_string); + + } else if (state == kim_credentials_state_not_yet_valid || + state == kim_credentials_state_needs_validation) { + err = kim_error_set_message_for_code (KIM_NEEDS_VALIDATION_ERR, + identity_string); + + } else if (state == kim_credentials_state_address_mismatch) { + err = kim_error_set_message_for_code (KIM_BAD_IP_ADDRESS_ERR, + identity_string); + } else { + /* just default to this */ + err = kim_error_set_message_for_code (KIM_NEEDS_VALIDATION_ERR, + identity_string); + } + } + + kim_string_free (&identity_string); + kim_identity_free (&identity); + } + + if (!err) { + *out_credential = credential; + credential = NULL; /* take ownership */ + } + + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_state (kim_ccache in_ccache, + kim_credential_state *out_state) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_state) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, + out_state, NULL, NULL); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_start_time (kim_ccache in_ccache, + kim_time *out_start_time) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_start_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, NULL, NULL, + &credential); + } + + if (!err) { + err = kim_credential_get_start_time (credential, out_start_time); + } + + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_expiration_time (kim_ccache in_ccache, + kim_time *out_expiration_time) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_expiration_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, NULL, NULL, + &credential); + } + + if (!err) { + err = kim_credential_get_expiration_time (credential, + out_expiration_time); + } + + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_renewal_expiration_time (kim_ccache in_ccache, + kim_time *out_renewal_expiration_time) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_renewal_expiration_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, NULL, NULL, + &credential); + } + + if (!err) { + err = kim_credential_get_renewal_expiration_time (credential, + out_renewal_expiration_time); + } + + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_get_options (kim_ccache in_ccache, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_dominant_credential (in_ccache, NULL, NULL, + &credential); + } + + if (!err) { + err = kim_credential_get_options (credential, out_options); + } + + kim_credential_free (&credential); + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_set_default (kim_ccache io_ccache) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + char *environment_ccache_name = getenv ("KRB5CCNAME"); + + if (environment_ccache_name) { + kim_ccache environment_ccache = NULL; + kim_comparison comparison; + + err = kim_ccache_create_from_display_name (&environment_ccache, + environment_ccache_name); + + if (!err) { + err = kim_ccache_compare (io_ccache, + environment_ccache, + &comparison); + } + + if (!err && !kim_comparison_is_equal_to (comparison)) { + krb5_principal client_principal = NULL; + + /* KRB5CCNAME is set and does not point to this ccache. + * Move the creds and make this kim_ccache_t object refer to that ccache. */ + + err = krb5_error (io_ccache->context, + krb5_cc_get_principal (io_ccache->context, + io_ccache->ccache, + &client_principal)); + + if (!err) { + err = krb5_error (io_ccache->context, + krb5_cc_initialize (environment_ccache->context, + environment_ccache->ccache, + client_principal)); + } + + if (!err) { + err = krb5_error (io_ccache->context, + krb5_cc_copy_creds (io_ccache->context, + io_ccache->ccache, + environment_ccache->ccache)); + } + + if (client_principal) { krb5_free_principal (io_ccache->context, + client_principal); } + + if (!err) { + kim_ccache_destroy (&io_ccache); + io_ccache = environment_ccache; + environment_ccache = NULL; /* take ownership */ + } + } + + kim_ccache_free (&environment_ccache); + + } else { +#ifdef USE_CCAPI + kim_string type = NULL; + kim_string name = NULL; + cc_context_t cc_context = NULL; + cc_ccache_t cc_ccache = NULL; + + err = kim_ccache_get_type (io_ccache, &type); + + if (!err && strcmp (type, "API")) { +#endif + kim_string display_name = NULL; + /* Not a CCAPI ccache; can't set to default */ + + err = kim_ccache_get_display_name (io_ccache, &display_name); + + if (!err) { + err = kim_error_set_message_for_code (KIM_CANT_BECOME_DEFAULT_ERR, + display_name); + } + + kim_string_free (&display_name); +#ifdef USE_CCAPI + } + + if (!err) { + err = kim_ccache_get_name (io_ccache, &name); + } + + /* get a CCAPI ccache for this cache */ + if (!err) { + err = cc_initialize (&cc_context, ccapi_version_4, NULL, NULL); + } + + if (!err) { + err = cc_context_open_ccache (cc_context, name, &cc_ccache); + } + + if (!err) { + err = cc_ccache_set_default (cc_ccache); + } + + if (cc_context) { cc_context_release (cc_context); } + if (cc_ccache ) { cc_ccache_release (cc_ccache); } + kim_string_free (&name); + kim_string_free (&type); +#endif + } + } + + return check_error (err); +} + +#ifndef LEAN_CLIENT + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_verify (kim_ccache in_ccache, + kim_identity in_service_identity, + kim_string in_keytab, + kim_boolean in_fail_if_no_service_key) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_valid_credential (in_ccache, &credential); + } + + if (!err) { + err = kim_credential_verify (credential, in_service_identity, + in_keytab, in_fail_if_no_service_key); + } + + kim_credential_free (&credential); + + return check_error (err); +} + +#endif /* LEAN_CLIENT */ + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_renew (kim_ccache in_ccache, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_identity client_identity = NULL; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_valid_credential (in_ccache, &credential); + } + + if (!err) { + err = kim_credential_renew (&credential, in_options); + } + + if (!err) { + err = kim_ccache_get_client_identity (in_ccache, &client_identity); + } + + if (!err) { + err = kim_credential_store (credential, client_identity, NULL); + } + + kim_identity_free (&client_identity); + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_validate (kim_ccache in_ccache, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_identity client_identity = NULL; + + if (!err && !in_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ccache_get_valid_credential (in_ccache, &credential); + } + + if (!err) { + err = kim_credential_validate (&credential, in_options); + } + + if (!err) { + err = kim_ccache_get_client_identity (in_ccache, &client_identity); + } + + if (!err) { + err = kim_credential_store (credential, client_identity, NULL); + } + + kim_identity_free (&client_identity); + kim_credential_free (&credential); + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ccache_destroy (kim_ccache *io_ccache) +{ + kim_error err = KIM_NO_ERROR; + + if (io_ccache && *io_ccache) { + err = krb5_error ((*io_ccache)->context, + krb5_cc_destroy ((*io_ccache)->context, + (*io_ccache)->ccache)); + + if (!err) { + (*io_ccache)->ccache = NULL; + kim_ccache_free (io_ccache); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_ccache_free (kim_ccache *io_ccache) +{ + if (io_ccache && *io_ccache) { + if ((*io_ccache)->context) { + if ((*io_ccache)->ccache) { + krb5_cc_close ((*io_ccache)->context, (*io_ccache)->ccache); + } + krb5_free_context ((*io_ccache)->context); + } + free (*io_ccache); + *io_ccache = NULL; + } +} + diff --git a/krb5-1-7/src/kim/lib/kim_credential.c b/krb5-1-7/src/kim/lib/kim_credential.c new file mode 100644 index 000000000..8d2c1ee60 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_credential.c @@ -0,0 +1,1416 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kim_private.h" + +struct kim_credential_iterator_opaque { + krb5_context context; + krb5_ccache ccache; + krb5_cc_cursor cursor; + krb5_flags old_flags; +}; + +struct kim_credential_iterator_opaque kim_credential_iterator_initializer = { NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_iterator_create (kim_credential_iterator *out_credential_iterator, + kim_ccache in_ccache) +{ + kim_error err = kim_library_init (); + kim_credential_iterator credential_iterator = NULL; + + if (!err && !out_credential_iterator) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_ccache ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + credential_iterator = malloc (sizeof (*credential_iterator)); + if (credential_iterator) { + *credential_iterator = kim_credential_iterator_initializer; + } else { + err = KIM_OUT_OF_MEMORY_ERR; + } + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&credential_iterator->context)); + } + + if (!err) { + err = kim_ccache_get_krb5_ccache (in_ccache, + credential_iterator->context, + &credential_iterator->ccache); + } + + if (!err) { + /* Turn off OPENCLOSE mode */ + err = krb5_error (credential_iterator->context, + krb5_cc_get_flags (credential_iterator->context, + credential_iterator->ccache, + &credential_iterator->old_flags)); + + if (!err && credential_iterator->old_flags & KRB5_TC_OPENCLOSE) { + krb5_flags new_flags = credential_iterator->old_flags & ~KRB5_TC_OPENCLOSE; + + err = krb5_error (credential_iterator->context, + krb5_cc_set_flags (credential_iterator->context, + credential_iterator->ccache, + new_flags)); + if (err == KRB5_FCC_NOFILE) { err = KIM_NO_ERROR; } + } + } + + if (!err) { + err = krb5_error (credential_iterator->context, + krb5_cc_start_seq_get (credential_iterator->context, + credential_iterator->ccache, + &credential_iterator->cursor)); + } + + if (!err) { + *out_credential_iterator = credential_iterator; + credential_iterator = NULL; + } + + kim_credential_iterator_free (&credential_iterator); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_iterator_next (kim_credential_iterator in_credential_iterator, + kim_credential *out_credential) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential_iterator) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + krb5_creds creds; + + krb5_error_code terr = krb5_cc_next_cred (in_credential_iterator->context, + in_credential_iterator->ccache, + &in_credential_iterator->cursor, + &creds); + + if (!terr) { + err = kim_credential_create_from_krb5_creds (out_credential, + in_credential_iterator->context, + &creds); + + krb5_free_cred_contents (in_credential_iterator->context, &creds); + + } else if (terr == KRB5_CC_END) { + *out_credential = NULL; /* no more ccaches */ + + } else { + err = krb5_error (in_credential_iterator->context, terr); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_credential_iterator_free (kim_credential_iterator *io_credential_iterator) +{ + if (io_credential_iterator && *io_credential_iterator) { + if ((*io_credential_iterator)->context) { + if ((*io_credential_iterator)->ccache) { + if ((*io_credential_iterator)->cursor) { + krb5_cc_end_seq_get ((*io_credential_iterator)->context, + (*io_credential_iterator)->ccache, + &(*io_credential_iterator)->cursor); + + krb5_cc_set_flags ((*io_credential_iterator)->context, + (*io_credential_iterator)->ccache, + (*io_credential_iterator)->old_flags); + } + krb5_cc_close ((*io_credential_iterator)->context, + (*io_credential_iterator)->ccache); + } + krb5_free_context ((*io_credential_iterator)->context); + } + free (*io_credential_iterator); + *io_credential_iterator = NULL; + } +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +struct kim_credential_opaque { + krb5_context context; + krb5_creds *creds; +}; + +struct kim_credential_opaque kim_credential_initializer = { NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_credential_allocate (kim_credential *out_credential) +{ + kim_error err = kim_library_init (); + kim_credential credential = NULL; + + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + credential = malloc (sizeof (*credential)); + if (!credential) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *credential = kim_credential_initializer; + *out_credential = credential; + credential = NULL; + } + + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_create_new (kim_credential *out_credential, + kim_identity in_identity, + kim_options in_options) +{ + return check_error (kim_credential_create_new_with_password (out_credential, + in_identity, + in_options, + NULL)); +} + +/* ------------------------------------------------------------------------ */ + +static void kim_credential_remember_prefs (kim_identity in_identity, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_boolean remember_identity = 0; + kim_boolean remember_options = 0; + + err = kim_preferences_create (&prefs); + + if (!err && in_options) { + err = kim_preferences_get_remember_options (prefs, + &remember_options); + } + + if (!err && in_identity) { + err = kim_preferences_get_remember_client_identity (prefs, + &remember_identity); + } + + if (!err && remember_options) { + err = kim_preferences_set_options (prefs, in_options); + } + + if (!err && remember_identity) { + err = kim_preferences_set_client_identity (prefs, in_identity); + + } + + if (!err && (remember_options || remember_identity)) { + err = kim_preferences_synchronize (prefs); + } + + kim_preferences_free (&prefs); + + check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_create_new_with_password (kim_credential *out_credential, + kim_identity in_identity, + kim_options in_options, + kim_string in_password) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_options options = NULL; + kim_ui_context context; + kim_boolean ui_inited = 0; + kim_boolean done_with_identity = 0; + + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&credential->context)); + } + + if (!err) { + if (in_options) { + options = in_options; + } else { + err = kim_options_create (&options); + } + } + + if (!err) { + err = kim_ui_init (&context); + if (!err) { ui_inited = 1; } + } + + while (!err && !done_with_identity) { + kim_identity identity = in_identity; + kim_boolean done_with_credentials = 0; + + if (identity) { + done_with_identity = 1; + + } else while (!err && !identity) { + kim_boolean user_wants_change_password = 0; + + err = kim_ui_enter_identity (&context, options, + &identity, + &user_wants_change_password); + + if (!err && user_wants_change_password) { + err = kim_identity_change_password_common (identity, 0, + &context, + NULL); + + /* reenter enter_identity so just forget this identity + * even if we got an error */ + if (err == KIM_USER_CANCELED_ERR || + err == KIM_DUPLICATE_UI_REQUEST_ERR) { + err = KIM_NO_ERROR; + } + + kim_identity_free (&identity); + } + + } + + if (!err) { + context.identity = identity; /* used by kim_ui_prompter */ + } + + while (!err && !done_with_credentials) { + krb5_creds creds; + kim_boolean free_creds = 0; + kim_count prompt_count; + krb5_principal principal = kim_identity_krb5_principal (identity); + krb5_get_init_creds_opt *opts = kim_options_init_cred_options (options); + char *service = kim_options_service_name (options); + kim_time start_time = kim_options_start_time (options); + + /* set counter to zero so we can tell if we got prompted */ + context.prompt_count = 0; + context.password_to_save = NULL; + + err = krb5_error (credential->context, + krb5_get_init_creds_password (credential->context, + &creds, + principal, + (char *) in_password, + kim_ui_prompter, + &context, + start_time, + service, + opts)); + + prompt_count = context.prompt_count; /* remember if we got prompts */ + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + + if (!err && context.password_to_save) { + /* If we were successful, save any password we got */ + err = kim_os_identity_set_saved_password (identity, + context.password_to_save); + + + } + + if (err == KRB5KDC_ERR_KEY_EXP) { + kim_string new_password = NULL; + + err = kim_identity_change_password_common (identity, 1, + &context, + &new_password); + + if (!err) { + /* set counter to zero so we can tell if we got prompted */ + context.prompt_count = 0; + + err = krb5_error (credential->context, + krb5_get_init_creds_password (credential->context, + &creds, + principal, + (char *) new_password, + kim_ui_prompter, + &context, + start_time, + service, + opts)); + + prompt_count = context.prompt_count; /* remember if we got prompts */ + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + } + + kim_string_free (&new_password); + } + + if (!err || err == KIM_USER_CANCELED_ERR || + err == KIM_DUPLICATE_UI_REQUEST_ERR) { + /* new creds obtained or the user gave up */ + done_with_credentials = 1; + + if (!err) { + /* remember identity and options if the user wanted to */ + kim_credential_remember_prefs (identity, options); + } + + if (err == KIM_DUPLICATE_UI_REQUEST_ERR) { + kim_ccache ccache = NULL; + /* credential for this identity was obtained, but via a different + * dialog. Find it. */ + + err = kim_ccache_create_from_client_identity (&ccache, + identity); + + if (!err) { + err = kim_ccache_get_valid_credential (ccache, + &credential); + } + + kim_ccache_free (&ccache); + } + + } else if (prompt_count) { + /* User was prompted and might have entered bad info + * so report error and try again. */ + + err = kim_ui_handle_kim_error (&context, identity, + kim_ui_error_type_authentication, + err); + } + + if (err == KRB5KRB_AP_ERR_BAD_INTEGRITY || + err == KRB5KDC_ERR_PREAUTH_FAILED || + err == KIM_BAD_PASSWORD_ERR || err == KIM_PREAUTH_FAILED_ERR) { + /* if the password could have failed, remove any saved ones + * or the user will get stuck. */ + kim_os_identity_remove_saved_password (identity); + } + + if (free_creds) { krb5_free_cred_contents (credential->context, &creds); } + } + + if (!err || err == KIM_USER_CANCELED_ERR) { + /* identity obtained or the user gave up */ + done_with_identity = 1; + + } else if (!in_identity) { + /* User entered an identity so report error and try again */ + err = kim_ui_handle_kim_error (&context, identity, + kim_ui_error_type_authentication, + err); + } + + if (identity != in_identity) { kim_identity_free (&identity); } + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = check_error (fini_err); } + } + + if (!err) { + *out_credential = credential; + credential = NULL; + } + + if (options != in_options) { kim_options_free (&options); } + kim_credential_free (&credential); + + return check_error (err); +} + +#ifndef LEAN_CLIENT + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_create_from_keytab (kim_credential *out_credential, + kim_identity in_identity, + kim_options in_options, + kim_string in_keytab) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + krb5_keytab keytab = NULL; + krb5_creds creds; + kim_boolean free_creds = FALSE; + krb5_principal principal = NULL; + kim_options options = in_options; + + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&credential->context)); + } + + if (!err && !options) { + err = kim_options_create (&options); + } + + if (!err) { + if (in_keytab) { + err = krb5_error (credential->context, + krb5_kt_resolve (credential->context, + in_keytab, &keytab)); + } else { + err = krb5_error (credential->context, + krb5_kt_default (credential->context, &keytab)); + } + } + + if (!err) { + if (in_identity) { + err = kim_identity_get_krb5_principal (in_identity, + credential->context, + &principal); + } else { + krb5_kt_cursor cursor = NULL; + krb5_keytab_entry entry; + kim_boolean entry_allocated = FALSE; + + err = krb5_error (credential->context, + krb5_kt_start_seq_get (credential->context, + keytab, + &cursor)); + + if (!err) { + err = krb5_error (credential->context, + krb5_kt_next_entry (credential->context, + keytab, + &entry, + &cursor)); + entry_allocated = (err == KIM_NO_ERROR); /* remember to free later */ + } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_principal (credential->context, + entry.principal, + &principal)); + } + + if (entry_allocated) { krb5_free_keytab_entry_contents (credential->context, &entry); } + if (cursor ) { krb5_kt_end_seq_get (credential->context, keytab, &cursor); } + } + } + + if (!err) { + krb5_get_init_creds_opt *opts = kim_options_init_cred_options (options); + char *service = kim_options_service_name (options); + kim_time start_time = kim_options_start_time (options); + + err = krb5_error (credential->context, + krb5_get_init_creds_keytab (credential->context, + &creds, + principal, + keytab, + start_time, + service, + opts)); + if (!err) { free_creds = TRUE; } + } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + + if (principal ) { krb5_free_principal (credential->context, principal); } + if (free_creds) { krb5_free_cred_contents (credential->context, &creds); } + + if (!err) { + *out_credential = credential; + credential = NULL; + } + + if (options != in_options) { kim_options_free (&options); } + kim_credential_free (&credential); + + return check_error (err); +} + +#endif /* LEAN_CLIENT */ + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential, + krb5_context in_krb5_context, + krb5_creds *in_krb5_creds) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_creds ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (in_krb5_context, + krb5_copy_context (in_krb5_context, + &credential->context)); + } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + in_krb5_creds, + &credential->creds)); + } + + if (!err) { + *out_credential = credential; + credential = NULL; + } + + return check_error (err); +} +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_create_for_change_password (kim_credential *out_credential, + kim_identity in_identity, + kim_string in_old_password, + kim_ui_context *in_ui_context, + kim_boolean *out_user_was_prompted) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_string realm = NULL; + kim_string service = NULL; + kim_string service_format = "kadmin/changepw@%s"; + + if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_user_was_prompted) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&credential->context)); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + err = kim_string_create_from_format (&service, service_format, realm); + } + + if (!err) { + krb5_creds creds; + kim_boolean free_creds = 0; + krb5_principal principal = kim_identity_krb5_principal (in_identity); + krb5_get_init_creds_opt opts; + + 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); + + /* set counter to zero so we can tell if we got prompted */ + in_ui_context->prompt_count = 0; + in_ui_context->identity = in_identity; + + err = krb5_error (credential->context, + krb5_get_init_creds_password (credential->context, + &creds, + principal, + (char *) in_old_password, + kim_ui_prompter, + in_ui_context, 0, + (char *) service, + &opts)); + + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + &creds, + &credential->creds)); + } + + if (free_creds) { krb5_free_cred_contents (credential->context, &creds); } + } + + if (!err) { + *out_user_was_prompted = (in_ui_context->prompt_count > 0); + *out_credential = credential; + credential = NULL; + } + + kim_string_free (&realm); + kim_string_free (&service); + kim_credential_free (&credential); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_copy (kim_credential *out_credential, + kim_credential in_credential) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + + if (!err && !out_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_allocate (&credential); + } + + if (!err) { + err = krb5_error (in_credential->context, + krb5_copy_context (in_credential->context, + &credential->context)); + } + + if (!err) { + err = krb5_error (credential->context, + krb5_copy_creds (credential->context, + in_credential->creds, + &credential->creds)); + } + + if (!err) { + *out_credential = credential; + credential = NULL; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_krb5_creds (kim_credential in_credential, + krb5_context in_krb5_context, + krb5_creds **out_krb5_creds) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_krb5_creds ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_error (in_krb5_context, + krb5_copy_creds (in_krb5_context, + in_credential->creds, + out_krb5_creds)); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_client_identity (kim_credential in_credential, + kim_identity *out_client_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_create_from_krb5_principal (out_client_identity, + in_credential->context, + in_credential->creds->client); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_service_identity (kim_credential in_credential, + kim_identity *out_service_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_service_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_create_from_krb5_principal (out_service_identity, + in_credential->context, + in_credential->creds->server); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_is_tgt (kim_credential in_credential, + kim_boolean *out_is_tgt) +{ + kim_error err = KIM_NO_ERROR; + kim_identity service = NULL; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_is_tgt ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_get_service_identity (in_credential, &service); + } + + if (!err) { + err = kim_identity_is_tgt_service (service, out_is_tgt); + } + + kim_identity_free (&service); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_state (kim_credential in_credential, + kim_credential_state *out_state) +{ + kim_error err = KIM_NO_ERROR; + kim_time expiration_time = 0; + kim_time start_time = 0; + krb5_timestamp now = 0; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_state ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_get_expiration_time (in_credential, &expiration_time); + } + + if (!err) { + err = kim_credential_get_start_time (in_credential, &start_time); + } + + if (!err) { + krb5_int32 usec; + + err = krb5_error (in_credential->context, + krb5_us_timeofday (in_credential->context, + &now, &usec)); + } + + if (!err) { + *out_state = kim_credentials_state_valid; + + if (expiration_time <= now) { + *out_state = kim_credentials_state_expired; + + } else if ((in_credential->creds->ticket_flags & TKT_FLG_POSTDATED) && + (in_credential->creds->ticket_flags & TKT_FLG_INVALID)) { + if (start_time > now) { + *out_state = kim_credentials_state_not_yet_valid; + } else { + *out_state = kim_credentials_state_needs_validation; + } + + } else if (in_credential->creds->addresses) { /* ticket contains addresses */ + krb5_address **laddresses = NULL; + + krb5_error_code code = krb5_os_localaddr (in_credential->context, + &laddresses); + if (!code) { laddresses = NULL; } + + if (laddresses) { /* assume valid if the local host has no addresses */ + kim_boolean found_match = FALSE; + kim_count i = 0; + + for (i = 0; in_credential->creds->addresses[i]; i++) { + if (!krb5_address_search (in_credential->context, + in_credential->creds->addresses[i], + laddresses)) { + found_match = TRUE; + break; + } + } + + if (!found_match) { + *out_state = kim_credentials_state_address_mismatch; + } + } + + if (laddresses) { krb5_free_addresses (in_credential->context, + laddresses); } + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_start_time (kim_credential in_credential, + kim_time *out_start_time) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_start_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_start_time = (in_credential->creds->times.starttime ? + in_credential->creds->times.starttime : + in_credential->creds->times.authtime); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_expiration_time (kim_credential in_credential, + kim_time *out_expiration_time) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_expiration_time = in_credential->creds->times.endtime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_renewal_expiration_time (kim_credential in_credential, + kim_time *out_renewal_expiration_time) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_renewal_expiration_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_credential->creds->ticket_flags & TKT_FLG_RENEWABLE) { + *out_renewal_expiration_time = in_credential->creds->times.renew_till; + } else { + *out_renewal_expiration_time = 0; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_get_options (kim_credential in_credential, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = NULL; + krb5_creds *creds = NULL; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + creds = in_credential->creds; + + err = kim_options_create (&options); + } + + if (!err) { + err = kim_options_set_start_time (options, creds->times.starttime); + } + + if (!err) { + kim_lifetime lifetime = (creds->times.endtime - + (creds->times.starttime ? + creds->times.starttime : + creds->times.authtime)); + + err = kim_options_set_lifetime (options, lifetime); + } + + if (!err) { + kim_boolean renewable = (creds->ticket_flags & TKT_FLG_RENEWABLE); + + err = kim_options_set_renewable (options, renewable); + } + + if (!err) { + kim_lifetime rlifetime = (creds->ticket_flags & TKT_FLG_RENEWABLE ? + creds->times.renew_till - + (creds->times.starttime ? + creds->times.starttime : + creds->times.authtime) : 0); + + err = kim_options_set_renewal_lifetime (options, rlifetime); + } + + if (!err) { + kim_boolean forwardable = (creds->ticket_flags & TKT_FLG_FORWARDABLE); + + err = kim_options_set_forwardable (options, forwardable); + } + + if (!err) { + kim_boolean proxiable = (creds->ticket_flags & TKT_FLG_PROXIABLE); + + err = kim_options_set_proxiable (options, proxiable); + } + + if (!err) { + kim_boolean addressless = (!creds->addresses || !creds->addresses[0]); + + err = kim_options_set_addressless (options, addressless); + } + + if (!err) { + kim_boolean is_tgt = 0; + kim_string service = NULL; /* tgt service */ + + err = kim_credential_is_tgt (in_credential, &is_tgt); + + if (!err && !is_tgt) { + kim_identity identity = NULL; + + err = kim_credential_get_service_identity (in_credential, &identity); + + if (!err) { + err = kim_identity_get_string (identity, &service); + } + + kim_identity_free (&identity); + } + + if (!err) { + err = kim_options_set_service_name (options, service); + } + + kim_string_free (&service); + } + + if (!err) { + *out_options = options; + options = NULL; + } + + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_store (kim_credential in_credential, + kim_identity in_identity, + kim_ccache *out_ccache) +{ + kim_error err = KIM_NO_ERROR; + krb5_ccache k5ccache = NULL; + kim_boolean destroy_ccache_on_error = FALSE; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + char *environment_ccache = getenv ("KRB5CCNAME"); + + if (environment_ccache) { + err = krb5_error (in_credential->context, + krb5_cc_resolve (in_credential->context, + environment_ccache, + &k5ccache)); + + } else { + kim_ccache ccache = NULL; + + err = kim_ccache_create_from_client_identity (&ccache, + in_identity); + + if (!err) { + err = kim_ccache_get_krb5_ccache (ccache, + in_credential->context, + &k5ccache); + + } else if (err == KIM_NO_SUCH_PRINCIPAL_ERR) { + /* Nothing to replace, create a new ccache */ + err = krb5_error (in_credential->context, + krb5_cc_new_unique (in_credential->context, + "API", NULL, &k5ccache)); + if (!err) { destroy_ccache_on_error = TRUE; } + } + + kim_ccache_free (&ccache); + } + } + + if (!err) { + krb5_principal principal = kim_identity_krb5_principal (in_identity); + + err = krb5_error (in_credential->context, + krb5_cc_initialize (in_credential->context, + k5ccache, principal)); + } + + if (!err) { + err = krb5_error (in_credential->context, + krb5_cc_store_cred (in_credential->context, + k5ccache, in_credential->creds)); + } + + if (!err && out_ccache) { + err = kim_ccache_create_from_krb5_ccache (out_ccache, + in_credential->context, + k5ccache); + } + + if (k5ccache) { + if (err && destroy_ccache_on_error) { + krb5_cc_destroy (in_credential->context, k5ccache); + } else { + krb5_cc_close (in_credential->context, k5ccache); + } + } + + return check_error (err); +} + +#ifndef LEAN_CLIENT + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_verify (kim_credential in_credential, + kim_identity in_service_identity, + kim_string in_keytab, + kim_boolean in_fail_if_no_service_key) +{ + kim_error err = KIM_NO_ERROR; + krb5_context scontext = NULL; + krb5_keytab keytab = NULL; + + if (!err && !in_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_error (NULL, krb5_init_secure_context (&scontext)); + } + + if (in_keytab) { + err = krb5_error (scontext, + krb5_kt_resolve (scontext, in_keytab, &keytab)); + } + + if (!err) { + krb5_principal sprincipal = NULL; + krb5_verify_init_creds_opt options; + + /* That's "no key == fail" not "no fail" >.< */ + krb5_verify_init_creds_opt_init (&options); + krb5_verify_init_creds_opt_set_ap_req_nofail (&options, in_fail_if_no_service_key); + + if (in_service_identity) { + sprincipal = kim_identity_krb5_principal (in_service_identity); + } + + err = krb5_error (scontext, + krb5_verify_init_creds (scontext, + in_credential->creds, + sprincipal, + keytab, + NULL /* don't store creds in ccache */, + &options)); + + if (err && !in_service_identity && in_fail_if_no_service_key) { + /* If the service principal wasn't specified but we are supposed to + * fail without a key we should walk the keytab trying to find one + * that succeeds. */ + krb5_error_code terr = 0; + kim_boolean verified = 0; + krb5_kt_cursor cursor = NULL; + krb5_keytab_entry entry; + + + if (!keytab) { + terr = krb5_kt_default (scontext, &keytab); + } + + if (!terr) { + terr = krb5_kt_start_seq_get (scontext, keytab, &cursor); + } + + while (!terr && !verified) { + kim_boolean free_entry = 0; + + terr = krb5_kt_next_entry (scontext, keytab, &entry, &cursor); + free_entry = !terr; /* remember to free */ + + if (!terr) { + terr = krb5_verify_init_creds (scontext, in_credential->creds, + entry.principal /* get principal for the 1st entry */, + keytab, + NULL /* don't store creds in ccache */, + &options); + } + + if (!terr) { + verified = 1; + } + + if (free_entry) { krb5_free_keytab_entry_contents (scontext, &entry); } + } + + if (!terr && verified) { + /* We found a key that verified! */ + err = KIM_NO_ERROR; + } + + if (cursor) { krb5_kt_end_seq_get (scontext, keytab, &cursor); } + } + } + + if (keytab ) { krb5_kt_close (scontext, keytab); } + if (scontext) { krb5_free_context (scontext); } + + return check_error (err); +} + +#endif /* LEAN_CLIENT */ + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_renew (kim_credential *io_credential, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_string service_name = NULL; + krb5_ccache ccache = NULL; + + if (!err && !io_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_options options = in_options; + + if (!options) { + err = kim_options_create (&options); + } + + if (!err) { + err = kim_options_get_service_name (options, &service_name); + } + + if (options != in_options) { kim_options_free (&options); } + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_new_unique ((*io_credential)->context, + "MEMORY", NULL, + &ccache)); + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_initialize ((*io_credential)->context, ccache, + (*io_credential)->creds->client)); + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_store_cred ((*io_credential)->context, ccache, + (*io_credential)->creds)); + } + + if (!err) { + krb5_creds creds; + krb5_creds *renewed_creds = NULL; + kim_boolean free_creds = 0; + + err = krb5_error ((*io_credential)->context, + krb5_get_renewed_creds ((*io_credential)->context, + &creds, (*io_credential)->creds->client, + ccache, (char *) service_name)); + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_copy_creds ((*io_credential)->context, + &creds, &renewed_creds)); + } + + if (!err) { + /* replace the credentials */ + krb5_free_creds ((*io_credential)->context, (*io_credential)->creds); + (*io_credential)->creds = renewed_creds; + } + + if (free_creds) { krb5_free_cred_contents ((*io_credential)->context, &creds); } + } + + if (ccache) { krb5_cc_destroy ((*io_credential)->context, ccache); } + kim_string_free (&service_name); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_credential_validate (kim_credential *io_credential, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_string service_name = NULL; + krb5_ccache ccache = NULL; + + if (!err && !io_credential) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_options options = in_options; + + if (!options) { + err = kim_options_create (&options); + } + + if (!err) { + err = kim_options_get_service_name (options, &service_name); + } + + if (options != in_options) { kim_options_free (&options); } + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_new_unique ((*io_credential)->context, + "MEMORY", NULL, + &ccache)); + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_initialize ((*io_credential)->context, ccache, + (*io_credential)->creds->client)); + } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_cc_store_cred ((*io_credential)->context, ccache, + (*io_credential)->creds)); + } + + if (!err) { + krb5_creds creds; + krb5_creds *validated_creds = NULL; + kim_boolean free_creds = 0; + + err = krb5_error ((*io_credential)->context, + krb5_get_validated_creds ((*io_credential)->context, + &creds, + (*io_credential)->creds->client, + ccache, + (char *) service_name)); + if (!err) { free_creds = 1; } + + if (!err) { + err = krb5_error ((*io_credential)->context, + krb5_copy_creds ((*io_credential)->context, + &creds, &validated_creds)); + } + + if (!err) { + /* replace the credentials */ + krb5_free_creds ((*io_credential)->context, (*io_credential)->creds); + (*io_credential)->creds = validated_creds; + } + + if (free_creds) { krb5_free_cred_contents ((*io_credential)->context, &creds); } + } + + if (ccache) { krb5_cc_destroy ((*io_credential)->context, ccache); } + kim_string_free (&service_name); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_credential_free (kim_credential *io_credential) +{ + if (io_credential && *io_credential) { + if ((*io_credential)->context) { + if ((*io_credential)->creds) { + krb5_free_creds ((*io_credential)->context, (*io_credential)->creds); + } + krb5_free_context ((*io_credential)->context); + } + free (*io_credential); + *io_credential = NULL; + } +} diff --git a/krb5-1-7/src/kim/lib/kim_credential_private.h b/krb5-1-7/src/kim/lib/kim_credential_private.h new file mode 100644 index 000000000..3f30d6c73 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_credential_private.h @@ -0,0 +1,39 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_CREDENTIAL_PRIVATE_H +#define KIM_CREDENTIAL_PRIVATE_H + +#include +#include "kim_ui_private.h" + +kim_error kim_credential_create_for_change_password (kim_credential *out_credential, + kim_identity in_identity, + kim_string in_old_password, + kim_ui_context *in_ui_context, + kim_boolean *out_user_was_prompted); + +#endif /* KIM_CREDENTIAL_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_debug.c b/krb5-1-7/src/kim/lib/kim_debug.c new file mode 100644 index 000000000..645a51f43 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_debug.c @@ -0,0 +1,76 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kim_private.h" + +/* ------------------------------------------------------------------------ */ + +kim_error _check_error (kim_error in_err, + kim_string in_function, + kim_string in_file, + int in_line) +{ + if (in_err) { + kim_debug_printf ("%s(): got %d ('%s') at %s: %d", + in_function, in_err, kim_error_message (in_err), + in_file, in_line); + } + + return in_err; +} + +/* ------------------------------------------------------------------------ */ + +void __kim_debug_printf (kim_string in_function, + kim_string in_format, + ...) +{ + kim_error err = KIM_NO_ERROR; + kim_string format = NULL; + kim_string string = NULL; + + if (!err && !in_function) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_create_from_format (&format, "%s(): %s", + in_function, in_format); + } + + if (!err) { + va_list args; + va_start (args, in_format); + err = kim_string_create_from_format_va (&string, format, args); + va_end (args); + } + + if (!err) { + kim_os_debug_print (string); + } + + kim_string_free (&format); + kim_string_free (&string); +} diff --git a/krb5-1-7/src/kim/lib/kim_debug_private.h b/krb5-1-7/src/kim/lib/kim_debug_private.h new file mode 100644 index 000000000..f9b67f0d9 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_debug_private.h @@ -0,0 +1,38 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 kim_debug_printf(format, ...) __kim_debug_printf(__FUNCTION__, format, ## __VA_ARGS__) +void __kim_debug_printf (kim_string in_function, + kim_string in_format, + ...); + +kim_error _check_error (kim_error in_err, + kim_string in_function, + kim_string in_file, + int in_line); +#define check_error(err) _check_error(err, __FUNCTION__, __FILE__, __LINE__) + +void kim_os_debug_print (kim_string in_string); diff --git a/krb5-1-7/src/kim/lib/kim_error_message.c b/krb5-1-7/src/kim/lib/kim_error_message.c new file mode 100644 index 000000000..6a891aa48 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_error_message.c @@ -0,0 +1,245 @@ +/* + * $Header$ + * + * 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. + */ + +#include "k5-int.h" +#include "kim_private.h" +#include +#include + +static k5_mutex_t kim_error_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +MAKE_INIT_FUNCTION(kim_error_initialize); +MAKE_FINI_FUNCTION(kim_error_terminate); + +/* ------------------------------------------------------------------------ */ + +typedef struct kim_last_error { + kim_error code; + char message[2048]; +} *kim_last_error; + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_error_set_message (kim_error in_error, + kim_string in_message) +{ + int lock_err = 0; + kim_error err = KIM_NO_ERROR; + kim_last_error last_error = NULL; + + err = lock_err = k5_mutex_lock (&kim_error_lock); + + if (!err) { + last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE); + + if (!last_error) { + last_error = malloc (sizeof (*last_error)); + if (!last_error) { + err = KIM_OUT_OF_MEMORY_ERR; + } else { + last_error->code = KIM_NO_ERROR; + err = k5_setspecific (K5_KEY_KIM_ERROR_MESSAGE, last_error); + } + } + } + + if (!err) { + strncpy (last_error->message, in_message, sizeof (last_error->message)); + last_error->message[sizeof (last_error->message)-1] = '\0'; + last_error->code = in_error; + } + + if (!lock_err) { k5_mutex_unlock (&kim_error_lock); } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void kim_error_free_message (void *io_error) +{ + kim_last_error error = io_error; + + if (error) { + if (error->message) { + free (error->message); + } + free (error); + } +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_boolean kim_error_is_builtin (kim_error in_error) +{ + return (in_error == KIM_NO_ERROR || + in_error == KIM_OUT_OF_MEMORY_ERR); +} + +/* ------------------------------------------------------------------------ */ +/* Warning: only remap to error strings with the same format! */ + +static kim_error kim_error_remap (kim_error in_error) +{ + /* some krb5 errors are confusing. remap to better ones */ + switch (in_error) { + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + return KIM_BAD_PASSWORD_ERR; + + case KRB5KDC_ERR_PREAUTH_FAILED: + return KIM_PREAUTH_FAILED_ERR; + + case KRB5KRB_AP_ERR_SKEW: + return KIM_CLOCK_SKEW_ERR; + } + + return in_error; +} + +/* ------------------------------------------------------------------------ */ + +kim_string kim_error_message (kim_error in_error) +{ + int lock_err = 0; + kim_last_error last_error = NULL; + kim_string message = NULL; + + lock_err = k5_mutex_lock (&kim_error_lock); + + if (!lock_err) { + last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE); + if (last_error && last_error->code == in_error) { + message = last_error->message; + } + } + + if (!lock_err) { k5_mutex_unlock (&kim_error_lock); } + + return message ? message : error_message (kim_error_remap (in_error)); +} + +#pragma mark -- Generic Functions -- + +/* ------------------------------------------------------------------------ */ + +kim_error kim_error_set_message_for_code (kim_error in_error, + ...) +{ + kim_error err = KIM_NO_ERROR; + va_list args; + + va_start (args, in_error); + err = kim_error_set_message_for_code_va (in_error, args); + va_end (args); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_error_set_message_for_code_va (kim_error in_code, + va_list in_args) +{ + kim_error err = KIM_NO_ERROR; + kim_error code = kim_error_remap (in_code); + + if (!kim_error_is_builtin (code)) { + kim_string message = NULL; + + err = kim_string_create_from_format_va_retcode (&message, + error_message (code), + in_args); + + if (!err) { + err = kim_error_set_message (code, message); + } + + kim_string_free (&message); + } + + return err ? err : code; +} + + +/* ------------------------------------------------------------------------ */ + +kim_error kim_error_set_message_for_krb5_error (krb5_context in_context, + krb5_error_code in_code) +{ + kim_error err = KIM_NO_ERROR; + krb5_error_code code = kim_error_remap (in_code); + + if (code != in_code) { + /* error was remapped to a KIM error */ + err = kim_error_set_message (code, error_message (code)); + + } else if (!kim_error_is_builtin (code)) { + const char *message = krb5_get_error_message (in_context, code); + + if (message) { + err = kim_error_set_message (code, message); + + krb5_free_error_message (in_context, message); + } + } + + return err ? err : code; +} + +#pragma mark -- Debugging Functions -- + +/* ------------------------------------------------------------------------ */ + +int kim_error_initialize (void) +{ + int err = 0; + + if (!err) { + err = k5_mutex_finish_init (&kim_error_lock); + } + + if (!err) { + err = k5_key_register (K5_KEY_KIM_ERROR_MESSAGE, + kim_error_free_message); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +void kim_error_terminate (void) +{ + if (!INITIALIZER_RAN (kim_error_initialize) || PROGRAM_EXITING ()) { + return; + } + + k5_key_delete (K5_KEY_KIM_ERROR_MESSAGE); + k5_mutex_destroy (&kim_error_lock); +} + diff --git a/krb5-1-7/src/kim/lib/kim_error_private.h b/krb5-1-7/src/kim/lib/kim_error_private.h new file mode 100644 index 000000000..72e409954 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_error_private.h @@ -0,0 +1,43 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_ERROR_PRIVATE_H +#define KIM_ERROR_PRIVATE_H + +#include + +kim_error kim_error_set_message_for_code (kim_error in_code, + ...); +kim_error kim_error_set_message_for_code_va (kim_error in_code, + va_list in_args); +kim_error kim_error_set_message_for_krb5_error (krb5_context in_context, + krb5_error_code in_code); + +#define krb5_error(context,code) kim_error_set_message_for_krb5_error(context, code) + +kim_string kim_error_message (kim_error in_error); + +#endif /* KIM_ERROR_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_errors.et b/krb5-1-7/src/kim/lib/kim_errors.et new file mode 100644 index 000000000..15f07be03 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_errors.et @@ -0,0 +1,76 @@ +# Copyright 2005-2006 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. + +error_table_manager "Kerberos Identity Management" +error_table KIM + +# Configuration and System Errors +error_code KIM_OUT_OF_MEMORY_ERR, "Out of memory" +error_code KIM_NULL_PARAMETER_ERR, "Parameter may not be NULL. Please consult the KIM API documentation" +error_code KIM_KRB5_INIT_FAILED_ERR, "Unable to initialize Kerberos v5" +error_code KIM_NO_REALMS_ERR, "There are no Kerberos realms configured" +error_code KIM_NO_SUCH_REALM_ERR, "The realm '%s' is not in your configuration file or does not exist" +error_code KIM_UNSUPPORTED_HINT_ERR, "The hint '%s' is not supported by this version of KIM" +error_code KIM_CLOCK_SKEW_ERR, "Clock skew too big: please check your time, time zone and daylight savings settings" + +index 25 +# Principal Errors +error_code KIM_BAD_PRINCIPAL_STRING_ERR, "'%s' is not a valid Kerberos principal" +error_code KIM_BAD_COMPONENT_INDEX_ERR, "Principal does not have a component at index %d" +error_code KIM_PASSWORD_MISMATCH_ERR, "New and verify passwords do not match" +error_code KIM_INSECURE_PASSWORD_ERR, "Your new password for '%s' is insecure; please pick another one" +error_code KIM_PASSWORD_CHANGE_FAILED_ERR, "Unable to change password for %s" +error_code KIM_BAD_PASSWORD_ERR, "Password incorrect" +error_code KIM_PREAUTH_FAILED_ERR, "Password incorrect or preauthentication failed" + +index 50 +# Options Errors +error_code KIM_BAD_OPTIONS_ERR, "Invalid options" +error_code KIM_BAD_OPTIONS_VALUE_ERR, "Invalid value for Kerberos default login option" + +index 75 +# User Interface Errors +error_code KIM_CAPS_LOCK_ERR, "Password Incorrect (check your Caps Lock)" +error_code KIM_USER_CANCELED_ERR, "The user cancelled the operation" +error_code KIM_NO_SERVER_ERR, "KerberosAgent is not responding" +error_code KIM_NO_UI_ERR, "Unable to display a user interface from this environment" +error_code KIM_DUPLICATE_UI_REQUEST_ERR, "UI just handled this request" + +index 100 +# Preferences Errors +error_code KIM_PREFERENCES_READ_ERR, "Unable to read user preferences. The file may be missing, inaccessible or corrupted" +error_code KIM_PREFERENCES_WRITE_ERR, "Unable to write user preferences. The file may be inaccessible" +error_code KIM_IDENTITY_NOT_IN_LIST_ERR, "Identity %s is not in the favorite identities list" +error_code KIM_IDENTITY_ALREADY_IN_LIST_ERR, "Identity %s is already in the favorite identities list" +error_code KIM_BAD_IDENTITY_INDEX_ERR, "No identity at index %d in the favorite identities list" + +index 125 +# Cache Collection Errors +error_code KIM_NO_SUCH_PRINCIPAL_ERR, "Principal '%s' does not exist in the cache collection" +error_code KIM_CANT_BECOME_DEFAULT_ERR, "The credentials cache '%s' cannot become the system default cache" +error_code KIM_CREDENTIALS_EXPIRED_ERR, "The Kerberos credentials for '%s' have expired" +error_code KIM_NO_CREDENTIALS_ERR, "No Kerberos credentials for '%s' available" +error_code KIM_BAD_IP_ADDRESS_ERR, "The IP addresses in the Kerberos credentials for '%s' do not match any of your computer's IP addresses" +error_code KIM_NO_SUCH_CCACHE_ERR, "The credentials cache '%s' does not exist" +error_code KIM_BAD_HOST_CONFIGURATION_ERR, "Unable to get local hostname or address information" +error_code KIM_NEEDS_VALIDATION_ERR, "The Kerberos credentials for '%s' need to be validated" + +end diff --git a/krb5-1-7/src/kim/lib/kim_identity.c b/krb5-1-7/src/kim/lib/kim_identity.c new file mode 100644 index 000000000..2a1ad5e3f --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_identity.c @@ -0,0 +1,802 @@ +/* + * $Header$ + * + * 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. + */ + +#include "k5-int.h" +#include +#include "kim_private.h" + +/* ------------------------------------------------------------------------ */ + +struct kim_identity_opaque { + krb5_context context; + krb5_principal principal; +}; + +struct kim_identity_opaque kim_identity_initializer = { NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_identity_allocate (kim_identity *out_identity) +{ + kim_error err = kim_library_init (); + kim_identity identity = NULL; + + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + identity = malloc (sizeof (*identity)); + if (!identity) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *identity = kim_identity_initializer; + *out_identity = identity; + identity = NULL; + } + + kim_identity_free (&identity); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_create_from_string (kim_identity *out_identity, + kim_string in_string) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_allocate (&identity); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&identity->context)); + } + + if (!err) { + krb5_error_code code = krb5_parse_name (identity->context, in_string, &identity->principal); + if (code == KRB5_PARSE_MALFORMED) { + err = kim_error_set_message_for_code (KIM_BAD_PRINCIPAL_STRING_ERR, + in_string); + } else if (code) { + err = krb5_error (identity->context, code); + } + } + + if (!err) { + *out_identity = identity; + identity = NULL; + } + + if (identity) { kim_identity_free (&identity); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_create_from_components (kim_identity *out_identity, + kim_string in_realm, + kim_string in_1st_component, + ...) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_realm ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_1st_component) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_allocate (&identity); + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&identity->context)); + } + + if (!err) { + va_list args; + + va_start (args, in_1st_component); + err = krb5_error (identity->context, + krb5int_build_principal_alloc_va (identity->context, + &identity->principal, + strlen(in_realm), + in_realm, + in_1st_component, + args)); + va_end (args); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + } + + kim_identity_free (&identity); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_create_from_krb5_principal (kim_identity *out_identity, + krb5_context in_krb5_context, + krb5_principal in_krb5_principal) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_principal) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* KLCreatePrincipalFromKerberos5Principal passes NULL in_krb5_context */ + + if (!err) { + err = kim_identity_allocate (&identity); + } + + if (!err) { + if (in_krb5_context) { + err = krb5_error (in_krb5_context, + krb5_copy_context (in_krb5_context, + &identity->context)); + } else { + err = krb5_error (NULL, + krb5_init_context (&identity->context)); + } + } + + if (!err) { + err = krb5_error (identity->context, + krb5_copy_principal (identity->context, + in_krb5_principal, + &identity->principal)); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + } + + kim_identity_free (&identity); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_copy (kim_identity *out_identity, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = KIM_IDENTITY_ANY; + + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && in_identity != KIM_IDENTITY_ANY) { + err = kim_identity_allocate (&identity); + + if (!err) { + err = krb5_error (in_identity->context, + krb5_copy_context (in_identity->context, + &identity->context)); + } + + if (!err) { + err = krb5_error (identity->context, + krb5_copy_principal (identity->context, + in_identity->principal, + &identity->principal)); + } + } + + if (!err) { + *out_identity = identity; + identity = NULL; + } + + kim_identity_free (&identity); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_compare (kim_identity in_identity, + kim_identity in_compare_to_identity, + kim_comparison *out_comparison) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_compare_to_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_comparison ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (krb5_principal_compare (in_identity->context, + in_identity->principal, + in_compare_to_identity->principal)) { + *out_comparison = 0; + } else { + kim_string string = NULL; + kim_string compare_to_string = NULL; + + err = kim_identity_get_string (in_identity, &string); + + if (!err) { + err = kim_identity_get_string (in_compare_to_identity, &compare_to_string); + } + + if (!err) { + err = kim_string_compare (string, compare_to_string, out_comparison); + } + + kim_string_free (&string); + kim_string_free (&compare_to_string); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_string (kim_identity in_identity, + kim_string *out_string) +{ + kim_error err = KIM_NO_ERROR; + char *unparsed_name = NULL; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_error (in_identity->context, + krb5_unparse_name (in_identity->context, + in_identity->principal, + &unparsed_name)); + } + + if (!err) { + err = kim_string_copy (out_string, unparsed_name); + } + + if (unparsed_name) { krb5_free_unparsed_name (in_identity->context, unparsed_name); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_display_string (kim_identity in_identity, + kim_string *out_display_string) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_display_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_string (in_identity, &string); + } + + if (!err) { + kim_count i, j; + kim_count length = strlen (string) + 1; /* Copy the '\0' */ + char *display_string = (char *) string; /* so we can modify it */ + + /* In place copy, skipping escaped separators. + * Note that we do not want to remove other escaped characters + * (tab, break, newline, NULL) because they are less readable + * when unescaped (and NULL isn't a valid string character). */ + for (i = 0, j = 0; i < length; i++) { + if (string[i] == '\\') { + switch (string[i + 1]) { + case '/': /* component separator */ + case '@': /* realm separator */ + continue; /* skip the '\' */ + } + } + + display_string[j++] = string[i]; /* Copy this char */ + } + + *out_display_string = string; + string = NULL; + } + + if (string) { kim_string_free (&string); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_realm (kim_identity in_identity, + kim_string *out_realm_string) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_realm_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + krb5_data *realm = krb5_princ_realm (in_identity->context, in_identity->principal); + + err = kim_string_create_from_buffer (out_realm_string, realm->data, realm->length); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_number_of_components (kim_identity in_identity, + kim_count *out_number_of_components) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_number_of_components) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_number_of_components = krb5_princ_size (in_identity->context, in_identity->principal); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_component_at_index (kim_identity in_identity, + kim_count in_index, + kim_string *out_component_string) +{ + kim_error err = KIM_NO_ERROR; + krb5_data *component = NULL; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_component_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + krb5_int32 i = in_index; + component = krb5_princ_component (in_identity->context, in_identity->principal, i); + if (!component) { + err = kim_error_set_message_for_code (KIM_BAD_COMPONENT_INDEX_ERR, i); + } + } + + if (!err) { + err = kim_string_create_from_buffer (out_component_string, component->data, component->length); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_components_string (kim_identity in_identity, + kim_string *out_components) +{ + kim_error err = KIM_NO_ERROR; + kim_string components = NULL; + kim_count count, i; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_components) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_number_of_components (in_identity, &count); + } + + if (!err) { + err = kim_identity_get_component_at_index (in_identity, 0, &components); + } + + for (i = 1; !err && i < count; i++) { + kim_string new_components = NULL; + kim_string component = NULL; + + err = kim_identity_get_component_at_index (in_identity, i, &component); + + if (!err) { + err = kim_string_create_from_format (&new_components, "%s/%s", + components, component); + } + + if (!err) { + kim_string_free (&components); + components = new_components; + new_components = NULL; + } + + if (component ) { kim_string_free (&component); } + if (new_components) { kim_string_free (&new_components); } + } + + if (!err) { + *out_components = components; + components = NULL; + } + + if (components) { kim_string_free (&components); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_get_krb5_principal (kim_identity in_identity, + krb5_context in_krb5_context, + krb5_principal *out_krb5_principal) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_krb5_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_krb5_principal) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_error (in_krb5_context, + krb5_copy_principal (in_krb5_context, + in_identity->principal, + out_krb5_principal)); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +krb5_principal kim_identity_krb5_principal (kim_identity in_identity) +{ + if (in_identity) { + return in_identity->principal; + } + check_error (KIM_NULL_PARAMETER_ERR); /* log error */ + return NULL; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_is_tgt_service (kim_identity in_identity, + kim_boolean *out_is_tgt_service) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_is_tgt_service) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_count count = krb5_princ_size (in_identity->context, in_identity->principal); + krb5_data *name = krb5_princ_name (in_identity->context, in_identity->principal); + + /* krbtgt/@ (usually REALM1 == REALM2, but not always) */ + *out_is_tgt_service = ((count == 2) && + (strlen (KRB5_TGS_NAME) == name->length) && + (strncmp (name->data, KRB5_TGS_NAME, name->length) == 0)); + } + + return check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_change_password_with_credential (kim_identity in_identity, + kim_credential in_credential, + kim_string in_new_password, + kim_ui_context *in_ui_context, + kim_error *out_rejected_err, + kim_string *out_rejected_message, + kim_string *out_rejected_description) +{ + kim_error err = KIM_NO_ERROR; + krb5_creds *creds = NULL; + int rejected_err = 0; + krb5_data message_data; + krb5_data description_data; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_ui_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_rejected_err) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_credential_get_krb5_creds (in_credential, + in_identity->context, + &creds); + } + + if (!err) { + if (krb5_principal_compare (in_identity->context, + in_identity->principal, + creds->client)) { + /* Same principal, change the password normally */ + err = krb5_error (in_identity->context, + krb5_change_password (in_identity->context, + creds, + (char *) in_new_password, + &rejected_err, + &message_data, + &description_data)); + } else { + /* Different principal, use set change password protocol */ + err = krb5_error (in_identity->context, + krb5_set_password (in_identity->context, + creds, + (char *) in_new_password, + in_identity->principal, + &rejected_err, + &message_data, + &description_data)); + } + + } + + if (!err && rejected_err) { + kim_string rejected_message = NULL; + kim_string rejected_description = NULL; + + if (message_data.data && message_data.length > 0) { + err = kim_string_create_from_buffer (&rejected_message, + message_data.data, + message_data.length); + } else { + err = kim_os_string_create_localized (&rejected_message, + "Kerberos Change Password Failed:"); + } + + if (!err) { + if (description_data.data && description_data.length > 0) { + err = kim_string_create_from_buffer (&rejected_description, + description_data.data, + description_data.length); + } else { + err = kim_os_string_create_localized (&rejected_description, + "New password rejected."); + } + } + + if (!err && in_ui_context->type != kim_ui_type_cli) { + char *c; + + // replace all \n and \r characters with spaces + for (c = (char *) rejected_message; *c != '\0'; c++) { + if ((*c == '\n') || (*c == '\r')) { *c = ' '; } + } + + for (c = (char *) rejected_description; *c != '\0'; c++) { + if ((*c == '\n') || (*c == '\r')) { *c = ' '; } + } + } + + if (!err) { + if (out_rejected_message) { + *out_rejected_message = rejected_message; + rejected_message = NULL; + } + if (out_rejected_description) { + *out_rejected_description = rejected_description; + rejected_description = NULL; + } + } + + kim_string_free (&rejected_message); + kim_string_free (&rejected_description); + + krb5_free_data_contents (in_identity->context, &message_data); + krb5_free_data_contents (in_identity->context, &description_data); + } + + if (!err) { + /* do this after reporting errors so we don't double report rejection */ + *out_rejected_err = rejected_err; + } + + if (creds) { krb5_free_creds (in_identity->context, creds); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_change_password_common (kim_identity in_identity, + kim_boolean in_old_password_expired, + kim_ui_context *in_ui_context, + kim_string *out_new_password) +{ + kim_error err = KIM_NO_ERROR; + kim_boolean done = 0; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_ui_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + while (!err && !done) { + char *old_password = NULL; + char *new_password = NULL; + char *verify_password = NULL; + kim_error rejected_err = KIM_NO_ERROR; + kim_string rejected_message = NULL; + kim_string rejected_description = NULL; + kim_boolean was_prompted = 0; /* ignore because we always prompt */ + + err = kim_ui_change_password (in_ui_context, + in_identity, + in_old_password_expired, + &old_password, + &new_password, + &verify_password); + + if (!err) { + kim_comparison comparison; + + err = kim_string_compare (new_password, + verify_password, + &comparison); + if (!err && !kim_comparison_is_equal_to (comparison)) { + err = check_error (KIM_PASSWORD_MISMATCH_ERR); + } + } + + if (!err) { + kim_credential credential = NULL; + + if (in_ui_context->type == kim_ui_type_cli && in_ui_context->tcontext) { + /* command line has already gotten the credentials for us */ + credential = (kim_credential) in_ui_context->tcontext; + } else { + err = kim_credential_create_for_change_password (&credential, + in_identity, + old_password, + in_ui_context, + &was_prompted); + } + + if (!err) { + err = kim_identity_change_password_with_credential (in_identity, + credential, + new_password, + in_ui_context, + &rejected_err, + &rejected_message, + &rejected_description); + } + + kim_credential_free (&credential); + if (in_ui_context->type == kim_ui_type_cli) { + in_ui_context->tcontext = NULL; /* just freed our creds */ + } + } + + if (!err && rejected_err) { + /* Password rejected, report it to the user */ + err = kim_ui_handle_error (in_ui_context, in_identity, + rejected_err, + rejected_message, + rejected_description); + + } else if (err && err != KIM_USER_CANCELED_ERR && + err != KIM_DUPLICATE_UI_REQUEST_ERR) { + /* New creds failed, report error to user. + * Overwrite error so we loop and let the user try again. + * The user always gets prompted so we always loop. */ + err = kim_ui_handle_kim_error (in_ui_context, in_identity, + kim_ui_error_type_change_password, + err); + + } else { + /* password change succeeded or the user gave up */ + done = 1; + + if (!err && out_new_password) { + err = kim_string_copy (out_new_password, new_password); + } + + if (!err) { + kim_error terr = KIM_NO_ERROR; + kim_string saved_password = NULL; + + terr = kim_os_identity_get_saved_password (in_identity, + &saved_password); + if (!terr) { + /* We changed the password and the user had their + * old password saved. Update it. */ + terr = kim_os_identity_set_saved_password (in_identity, + new_password); + } + + kim_string_free (&saved_password); + } + + if (err == KIM_DUPLICATE_UI_REQUEST_ERR) { err = KIM_NO_ERROR; } + } + + kim_string_free (&rejected_message); + kim_string_free (&rejected_description); + + kim_ui_free_string (in_ui_context, &old_password); + kim_ui_free_string (in_ui_context, &new_password); + kim_ui_free_string (in_ui_context, &verify_password); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_identity_change_password (kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_ui_context context; + kim_boolean ui_inited = 0; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_init (&context); + if (!err) { ui_inited = 1; } + } + + if (!err) { + err = kim_identity_change_password_common (in_identity, 0, + &context, NULL); + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = check_error (fini_err); } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_identity_free (kim_identity *io_identity) +{ + if (io_identity && *io_identity) { + kim_identity identity = *io_identity; + + if (identity->context) { + if (identity->principal) { + krb5_free_principal (identity->context, identity->principal); + } + krb5_free_context (identity->context); + } + + free (identity); + *io_identity = NULL; + } +} diff --git a/krb5-1-7/src/kim/lib/kim_identity_private.h b/krb5-1-7/src/kim/lib/kim_identity_private.h new file mode 100644 index 000000000..43c197d73 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_identity_private.h @@ -0,0 +1,66 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_IDENTITY_PRIVATE_H +#define KIM_IDENTITY_PRIVATE_H + +#include +#include "kim_library_private.h" +#include "kim_ui_private.h" + +krb5_principal kim_identity_krb5_principal (kim_identity in_identity); + +kim_error kim_identity_is_tgt_service (kim_identity in_identity, + kim_boolean *out_is_tgt_service); + + +kim_error kim_os_identity_create_for_username (kim_identity *out_identity); + + +kim_boolean kim_os_identity_allow_save_password (void); + +kim_error kim_os_identity_get_saved_password (kim_identity in_identity, + kim_string *out_password); + +kim_error kim_os_identity_set_saved_password (kim_identity in_identity, + kim_string in_password); + +kim_error kim_os_identity_remove_saved_password (kim_identity in_identity); + +kim_error kim_identity_change_password_with_credential (kim_identity in_identity, + kim_credential in_credential, + kim_string in_new_password, + kim_ui_context *in_ui_context, + kim_error *out_rejected_err, + kim_string *out_rejected_message, + kim_string *out_rejected_description); + +kim_error kim_identity_change_password_common (kim_identity in_identity, + kim_boolean in_old_password_expired, + kim_ui_context *in_ui_context, + kim_string *out_new_password); + +#endif /* KIM_IDENTITY_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_library.c b/krb5-1-7/src/kim/lib/kim_library.c new file mode 100644 index 000000000..0272aa7fd --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_library.c @@ -0,0 +1,403 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KRB5_PRIVATE 1 + +#include "k5-int.h" +#include "k5-thread.h" +#include +#include + +#include "kim_private.h" +#include "kim_os_private.h" + +#if KIM_TO_KLL_SHIM +#include "KerberosLoginErrors.h" +#endif + +MAKE_INIT_FUNCTION(kim_error_init); +MAKE_FINI_FUNCTION(kim_error_fini); + +/* ------------------------------------------------------------------------ */ + +static int kim_error_init (void) +{ + add_error_table (&et_KIM_error_table); +#if KIM_TO_KLL_SHIM + add_error_table (&et_KLL_error_table); +#endif + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static void kim_error_fini (void) +{ + if (!INITIALIZER_RAN (kim_error_init) || PROGRAM_EXITING ()) { + return; + } + + remove_error_table (&et_KIM_error_table); +#if KIM_TO_KLL_SHIM + remove_error_table (&et_KLL_error_table); +#endif +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_init (void) +{ + return CALL_INIT_FUNCTION (kim_error_init); +} + +#pragma mark - + +static k5_mutex_t g_allow_home_directory_access_mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static k5_mutex_t g_allow_automatic_prompting_mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static k5_mutex_t g_ui_environment_mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static k5_mutex_t g_application_name_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +kim_boolean g_allow_home_directory_access = TRUE; +kim_boolean g_allow_automatic_prompting = TRUE; +kim_ui_environment g_ui_environment = KIM_UI_ENVIRONMENT_AUTO; +kim_string g_application_name = NULL; + +MAKE_INIT_FUNCTION(kim_thread_init); +MAKE_FINI_FUNCTION(kim_thread_fini); + +/* ------------------------------------------------------------------------ */ + +static int kim_thread_init (void) +{ + kim_error err = KIM_NO_ERROR; + + if (!err) { + err = k5_mutex_finish_init (&g_allow_home_directory_access_mutex); + } + + if (!err) { + err = k5_mutex_finish_init (&g_allow_automatic_prompting_mutex); + } + + if (!err) { + err = k5_mutex_finish_init (&g_ui_environment_mutex); + } + + if (!err) { + err = k5_mutex_finish_init (&g_application_name_mutex); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void kim_thread_fini (void) +{ + if (!INITIALIZER_RAN (kim_thread_init) || PROGRAM_EXITING ()) { + return; + } + + k5_mutex_destroy (&g_allow_home_directory_access_mutex); + k5_mutex_destroy (&g_allow_automatic_prompting_mutex); + k5_mutex_destroy (&g_ui_environment_mutex); + k5_mutex_destroy (&g_application_name_mutex); +} + +#pragma mark -- Allow Home Directory Access -- + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_set_allow_home_directory_access (kim_boolean in_allow_access) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err) { + mutex_err = k5_mutex_lock (&g_allow_home_directory_access_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + g_allow_home_directory_access = in_allow_access; + } + + if (!mutex_err) { k5_mutex_unlock (&g_allow_home_directory_access_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_library_get_allow_home_directory_access (kim_boolean *out_allow_access) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err && !out_allow_access) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + mutex_err = k5_mutex_lock (&g_allow_home_directory_access_mutex);; + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + *out_allow_access = g_allow_home_directory_access; + } + + if (!mutex_err) { k5_mutex_unlock (&g_allow_home_directory_access_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_boolean kim_library_allow_home_directory_access (void) +{ + kim_boolean allow_access = FALSE; + kim_error err = kim_library_get_allow_home_directory_access (&allow_access); + + return !err ? allow_access : FALSE; +} + + +#pragma mark -- Allow Automatic Prompting -- + + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_set_allow_automatic_prompting (kim_boolean in_allow_automatic_prompting) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err) { + mutex_err = k5_mutex_lock (&g_allow_automatic_prompting_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + g_allow_automatic_prompting = in_allow_automatic_prompting; + } + + if (!mutex_err) { k5_mutex_unlock (&g_allow_automatic_prompting_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_library_get_allow_automatic_prompting (kim_boolean *out_allow_automatic_prompting) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err && !out_allow_automatic_prompting) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + mutex_err = k5_mutex_lock (&g_allow_automatic_prompting_mutex);; + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + *out_allow_automatic_prompting = g_allow_automatic_prompting; + } + + if (!mutex_err) { k5_mutex_unlock (&g_allow_automatic_prompting_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_boolean kim_library_allow_automatic_prompting (void) +{ + kim_boolean allow_automatic_prompting = TRUE; + kim_error err = kim_library_get_allow_automatic_prompting (&allow_automatic_prompting); + if (err) { allow_automatic_prompting = TRUE; } + + if (allow_automatic_prompting && getenv ("KERBEROSLOGIN_NEVER_PROMPT")) { + kim_debug_printf ("KERBEROSLOGIN_NEVER_PROMPT is set."); + allow_automatic_prompting = FALSE; + } + + if (allow_automatic_prompting && getenv ("KIM_NEVER_PROMPT")) { + kim_debug_printf ("KIM_NEVER_PROMPT is set."); + allow_automatic_prompting = FALSE; + } + + if (allow_automatic_prompting && !kim_os_library_caller_uses_gui ()) { + kim_debug_printf ("Caller is not using gui."); + allow_automatic_prompting = FALSE; + } + + if (allow_automatic_prompting) { + /* Make sure there is at least 1 config file. We don't support DNS + * domain-realm lookup, so if there is no config, Kerberos won't work. */ + + kim_boolean kerberos_config_exists = FALSE; + char **files = NULL; + profile_t profile = NULL; + + if (krb5_get_default_config_files (&files) == 0) { + if (profile_init ((const_profile_filespec_t *) files, &profile) == 0) { + kerberos_config_exists = TRUE; + } + } + + if (!kerberos_config_exists) { + kim_debug_printf ("No valid config file."); + allow_automatic_prompting = FALSE; + } + + if (profile) { profile_abandon (profile); } + if (files ) { krb5_free_config_files (files); } + } + + return allow_automatic_prompting; +} + +#pragma mark -- UI Environment -- + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_set_ui_environment (kim_ui_environment in_ui_environment) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err) { + mutex_err = k5_mutex_lock (&g_ui_environment_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + g_ui_environment = in_ui_environment; + } + + if (!mutex_err) { k5_mutex_unlock (&g_ui_environment_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_library_get_ui_environment (kim_ui_environment *out_ui_environment) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err && !out_ui_environment) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + mutex_err = k5_mutex_lock (&g_ui_environment_mutex);; + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + *out_ui_environment = g_ui_environment; + } + + if (!mutex_err) { k5_mutex_unlock (&g_ui_environment_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_ui_environment kim_library_ui_environment (void) +{ + kim_error err = KIM_NO_ERROR; + kim_ui_environment ui_environment = KIM_UI_ENVIRONMENT_AUTO; + + err = kim_library_get_ui_environment (&ui_environment); + + if (!err && ui_environment == KIM_UI_ENVIRONMENT_AUTO) { + ui_environment = kim_os_library_get_ui_environment (); + } + + return !err ? ui_environment : KIM_UI_ENVIRONMENT_NONE; +} + +#pragma mark -- Application Name -- + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_set_application_name (kim_string in_application_name) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + + if (!err) { + mutex_err = k5_mutex_lock (&g_application_name_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + kim_string old_application_name = g_application_name; + + if (in_application_name) { + err = kim_string_copy (&g_application_name, in_application_name); + } else { + g_application_name = NULL; + } + + if (!err) { kim_string_free (&old_application_name); } + } + + if (!mutex_err) { k5_mutex_unlock (&g_application_name_mutex); } + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_library_get_application_name (kim_string *out_application_name) +{ + kim_error err = CALL_INIT_FUNCTION (kim_thread_init); + kim_error mutex_err = KIM_NO_ERROR; + kim_string application_name = NULL; + + if (!err && !out_application_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + mutex_err = k5_mutex_lock (&g_application_name_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err && g_application_name) { + err = kim_string_copy (&application_name, g_application_name); + } + + if (!mutex_err) { k5_mutex_unlock (&g_application_name_mutex); } + + if (!err && !application_name) { + err = kim_os_library_get_caller_name (&application_name); + } + + if (!err) { + *out_application_name = application_name; + application_name = NULL; + + } + + kim_string_free (&application_name); + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/kim_library_private.h b/krb5-1-7/src/kim/lib/kim_library_private.h new file mode 100644 index 000000000..146474b0e --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_library_private.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_LIBRARY_PRIVATE_H +#define KIM_LIBRARY_PRIVATE_H + +#include +#include + +kim_error kim_library_init (void); + +kim_boolean kim_os_library_caller_uses_gui (void); + +kim_ui_environment kim_os_library_get_ui_environment (void); + +kim_ui_environment kim_library_ui_environment (void); + +kim_boolean kim_library_allow_home_directory_access (void); + +kim_boolean kim_library_allow_automatic_prompting (void); + +kim_error kim_library_get_application_name (kim_string *out_application_name); + +/* OS-specific. Call kim_library_get_application_name */ +kim_error kim_os_library_get_caller_name (kim_string *out_application_name); + +kim_boolean kim_os_library_caller_is_server (void); + +#endif /* KIM_LIBRARY_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_options.c b/krb5-1-7/src/kim/lib/kim_options.c new file mode 100644 index 000000000..5d7e58ae5 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_options.c @@ -0,0 +1,670 @@ +/* + * $Header$ + * + * 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. + */ + +#include "kim_private.h" + +/* ------------------------------------------------------------------------ */ + +struct kim_options_opaque { + kim_time start_time; + kim_lifetime lifetime; + kim_boolean renewable; + kim_lifetime renewal_lifetime; + kim_boolean forwardable; + kim_boolean proxiable; + kim_boolean addressless; + kim_string service_name; + krb5_context init_cred_context; + krb5_get_init_creds_opt *init_cred_options; +}; + +struct kim_options_opaque kim_options_initializer = { +0, +kim_default_lifetime, +kim_default_renewable, +kim_default_renewal_lifetime, +kim_default_forwardable, +kim_default_proxiable, +kim_default_addressless, +kim_empty_string, +NULL, +NULL }; + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_options_allocate (kim_options *out_options) +{ + kim_error err = kim_library_init (); + kim_options options = NULL; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + options = malloc (sizeof (*options)); + if (!options) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *options = kim_options_initializer; + *out_options = options; + options = NULL; + } + + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_create_empty (kim_options *out_options) +{ + return check_error (kim_options_allocate (out_options)); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_create (kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences preferences = NULL; + kim_options options = KIM_OPTIONS_DEFAULT; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_preferences_create (&preferences); + } + + if (!err) { + err = kim_preferences_get_options (preferences, &options); + } + + if (!err && !options) { + err = kim_options_allocate (&options); + } + + if (!err) { + *out_options = options; + options = NULL; /* caller takes ownership */ + } + + kim_options_free (&options); + kim_preferences_free (&preferences); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_copy (kim_options *out_options, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = KIM_OPTIONS_DEFAULT; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && in_options != KIM_OPTIONS_DEFAULT) { + err = kim_options_allocate (&options); + + if (!err) { + options->start_time = in_options->start_time; + options->lifetime = in_options->lifetime; + options->renewable = in_options->renewable; + options->renewal_lifetime = in_options->renewal_lifetime; + options->forwardable = in_options->forwardable; + options->proxiable = in_options->proxiable; + options->addressless = in_options->addressless; + + if (in_options->service_name) { + err = kim_string_copy (&options->service_name, + in_options->service_name); + } + } + } + + if (!err) { + *out_options = options; + options = NULL; + } + + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_start_time (kim_options io_options, + kim_time in_start_time) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->start_time = in_start_time; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_start_time (kim_options in_options, + kim_time *out_start_time) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_start_time) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_start_time = in_options->start_time; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_lifetime (kim_options io_options, + kim_lifetime in_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->lifetime = in_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_lifetime (kim_options in_options, + kim_lifetime *out_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_lifetime = in_options->lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_renewable (kim_options io_options, + kim_boolean in_renewable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->renewable = in_renewable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_renewable (kim_options in_options, + kim_boolean *out_renewable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_renewable) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_renewable = in_options->renewable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_renewal_lifetime (kim_options io_options, + kim_lifetime in_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->renewal_lifetime = in_renewal_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_renewal_lifetime (kim_options in_options, + kim_lifetime *out_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_renewal_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_renewal_lifetime = in_options->renewal_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_forwardable (kim_options io_options, + kim_boolean in_forwardable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->forwardable = in_forwardable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_forwardable (kim_options in_options, + kim_boolean *out_forwardable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_forwardable) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_forwardable = in_options->forwardable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_proxiable (kim_options io_options, + kim_boolean in_proxiable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->proxiable = in_proxiable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_proxiable (kim_options in_options, + kim_boolean *out_proxiable) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_proxiable) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_proxiable = in_options->proxiable; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_addressless (kim_options io_options, + kim_boolean in_addressless) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_options->addressless = in_addressless; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_addressless (kim_options in_options, + kim_boolean *out_addressless) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_addressless) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_addressless = in_options->addressless; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_set_service_name (kim_options io_options, + kim_string in_service_name) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_string_free (&io_options->service_name); + if (in_service_name) { + err = kim_string_copy (&io_options->service_name, in_service_name); + } else { + io_options->service_name = kim_empty_string; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_get_service_name (kim_options in_options, + kim_string *out_service_name) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_service_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_options->service_name && + in_options->service_name != kim_empty_string) { + err = kim_string_copy (out_service_name, in_options->service_name); + } else { + *out_service_name = NULL; + } + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +char *kim_options_service_name (kim_options in_options) +{ + if (in_options) { + if (in_options->service_name == kim_empty_string) { + return NULL; + } else { + return (char *) in_options->service_name; + } + } + check_error (KIM_NULL_PARAMETER_ERR); /* log bad options input */ + return NULL; +} + +/* ------------------------------------------------------------------------ */ + +kim_time kim_options_start_time (kim_options in_options) +{ + if (in_options) { + return in_options->start_time; + } + check_error (KIM_NULL_PARAMETER_ERR); /* log bad options input */ + return 0; +} + +/* ------------------------------------------------------------------------ */ + +krb5_get_init_creds_opt *kim_options_init_cred_options (kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + krb5_address **addresses = NULL; + + if (!err && !in_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !in_options->init_cred_context) { + err = krb5_error (NULL, + krb5_init_context (&in_options->init_cred_context)); + } + + if (!err && !in_options->addressless) { + err = krb5_error (in_options->init_cred_context, + krb5_os_localaddr (in_options->init_cred_context, + &addresses)); + } + + if (!err && !in_options->init_cred_options) { + err = krb5_error (in_options->init_cred_context, + krb5_get_init_creds_opt_alloc (in_options->init_cred_context, + &in_options->init_cred_options)); + } + + if (!err) { + krb5_get_init_creds_opt_set_tkt_life (in_options->init_cred_options, + in_options->lifetime); + krb5_get_init_creds_opt_set_renew_life (in_options->init_cred_options, + in_options->renewable ? in_options->renewal_lifetime : 0); + krb5_get_init_creds_opt_set_forwardable (in_options->init_cred_options, + in_options->forwardable); + krb5_get_init_creds_opt_set_proxiable (in_options->init_cred_options, + in_options->proxiable); + krb5_get_init_creds_opt_set_address_list (in_options->init_cred_options, + addresses); + addresses = NULL; + } + + if (addresses) { krb5_free_addresses (in_options->init_cred_context, + addresses); } + + return !check_error (err) ? in_options->init_cred_options : NULL; +} + +/* ------------------------------------------------------------------------ */ + +void kim_options_free (kim_options *io_options) +{ + if (io_options && *io_options) { + kim_string_free (&(*io_options)->service_name); + if ((*io_options)->init_cred_context) { + if ((*io_options)->init_cred_options) { + if ((*io_options)->init_cred_options->address_list) { + krb5_free_addresses ((*io_options)->init_cred_context, + (*io_options)->init_cred_options->address_list); + } + krb5_get_init_creds_opt_free ((*io_options)->init_cred_context, + (*io_options)->init_cred_options); + } + krb5_free_context ((*io_options)->init_cred_context); + } + + free (*io_options); + *io_options = NULL; + } +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_write_to_stream (kim_options in_options, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = in_options; + + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !in_options) { + err = kim_options_create (&options); + } + + if (!err) { + err = k5_ipc_stream_write_int64 (io_stream, options->start_time); + } + + if (!err) { + err = k5_ipc_stream_write_int64 (io_stream, options->lifetime); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (io_stream, options->renewable); + } + + if (!err) { + err = k5_ipc_stream_write_int64 (io_stream, + options->renewal_lifetime); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (io_stream, options->forwardable); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (io_stream, options->proxiable); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (io_stream, options->addressless); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, options->service_name); + } + + if (options != in_options) { kim_options_free (&options); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_read_from_stream (kim_options io_options, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = k5_ipc_stream_read_int64 (io_stream, &io_options->start_time); + } + + if (!err) { + err = k5_ipc_stream_read_int64 (io_stream, &io_options->lifetime); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (io_stream, &io_options->renewable); + } + + if (!err) { + err = k5_ipc_stream_read_int64 (io_stream, + &io_options->renewal_lifetime); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (io_stream, &io_options->forwardable); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (io_stream, &io_options->proxiable); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (io_stream, &io_options->addressless); + } + + if (!err) { + char *service_name = NULL; + err = k5_ipc_stream_read_string (io_stream, &service_name); + + if (!err) { + kim_string_free (&io_options->service_name); + if (service_name[0]) { + err = kim_string_copy (&io_options->service_name, service_name); + } else { + io_options->service_name = kim_empty_string; + } + } + + k5_ipc_stream_free_string (service_name); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_options_create_from_stream (kim_options *out_options, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = NULL; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_allocate (&options); + } + + if (!err) { + kim_options_read_from_stream (options, io_stream); + } + + if (!err) { + *out_options = options; + options = NULL; + } + + kim_options_free (&options); + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/kim_options_private.h b/krb5-1-7/src/kim/lib/kim_options_private.h new file mode 100644 index 000000000..42a9d7855 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_options_private.h @@ -0,0 +1,51 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_OPTIONS_PRIVATE_H +#define KIM_OPTIONS_PRIVATE_H + +#include +#include "k5-ipc_stream.h" + +kim_error kim_options_create_empty (kim_options *out_options); + +krb5_get_init_creds_opt *kim_options_init_cred_options (kim_options in_options); + +char *kim_options_service_name (kim_options in_options); + +kim_time kim_options_start_time (kim_options in_options); + + +kim_error kim_options_write_to_stream (kim_options in_options, + k5_ipc_stream io_stream); + +kim_error kim_options_read_from_stream (kim_options io_options, + k5_ipc_stream io_stream); + +kim_error kim_options_create_from_stream (kim_options *out_options, + k5_ipc_stream io_stream); + +#endif /* KIM_OPTIONS_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_preferences.c b/krb5-1-7/src/kim/lib/kim_preferences.c new file mode 100644 index 000000000..a9bd6ce55 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_preferences.c @@ -0,0 +1,1088 @@ +/* + * $Header$ + * + * 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. + */ + +#include "kim_private.h" + +struct kim_favorites_opaque { + kim_count count; + kim_identity *identities; + kim_options *options; +}; + +struct kim_preferences_opaque { + kim_options options; + kim_boolean options_changed; + kim_boolean remember_options; + kim_boolean remember_options_changed; + kim_identity client_identity; + kim_boolean client_identity_changed; + kim_boolean remember_client_identity; + kim_boolean remember_client_identity_changed; + kim_lifetime minimum_lifetime; + kim_lifetime maximum_lifetime; + kim_boolean lifetime_range_changed; + kim_lifetime minimum_renewal_lifetime; + kim_lifetime maximum_renewal_lifetime; + kim_boolean renewal_lifetime_range_changed; + struct kim_favorites_opaque favorites; + kim_boolean favorites_changed; +}; + +const struct kim_favorites_opaque kim_default_favorites = { 0, NULL, NULL }; + +struct kim_preferences_opaque kim_preferences_initializer = { +KIM_OPTIONS_DEFAULT, +FALSE, +kim_default_remember_options, +FALSE, +kim_default_client_identity, +FALSE, +kim_default_remember_client_identity, +FALSE, +kim_default_minimum_lifetime, +kim_default_maximum_lifetime, +FALSE, +kim_default_minimum_renewal_lifetime, +kim_default_maximum_renewal_lifetime, +FALSE, +{ 0, NULL, NULL }, +FALSE +}; + + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_favorites_resize (kim_favorites io_favorites, + kim_count in_new_count) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && io_favorites->count != in_new_count) { + kim_identity *identities = NULL; + kim_options *options = NULL; + + if (in_new_count == 0) { + if (io_favorites->identities) { + free (io_favorites->identities); + } + if (io_favorites->options) { + free (io_favorites->options); + } + } else { + if (!io_favorites->identities) { + identities = malloc (sizeof (*identities) * in_new_count); + } else { + identities = realloc (io_favorites->identities, + sizeof (*identities) * in_new_count); + } + if (!identities) { err = KIM_OUT_OF_MEMORY_ERR; } + + if (!err) { + if (!io_favorites->options) { + options = malloc (sizeof (*options) * in_new_count); + } else { + options = realloc (io_favorites->options, + sizeof (*options) * in_new_count); + } + if (!options) { err = KIM_OUT_OF_MEMORY_ERR; } + } + } + + if (!err) { + io_favorites->count = in_new_count; + io_favorites->identities = identities; + io_favorites->options = options; + identities = NULL; + options = NULL; + } + + if (identities) { free (identities); } + if (options ) { free (options); } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_favorites_copy (kim_favorites in_favorites, + kim_favorites io_favorites) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_favorites_resize (io_favorites, in_favorites->count); + } + + if (!err) { + kim_count i; + + for (i = 0; !err && i < io_favorites->count; i++) { + err = kim_identity_copy (&io_favorites->identities[i], + in_favorites->identities[i]); + + if (!err) { + err = kim_options_copy (&io_favorites->options[i], + in_favorites->options[i]); + } + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_favorites_get_number_of_identities (kim_favorites in_favorites, + kim_count *out_number_of_identities) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_favorites ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_number_of_identities) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_number_of_identities = in_favorites->count; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_favorites_get_identity_at_index (kim_favorites in_favorites, + kim_count in_index, + kim_identity *out_identity, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_options options = KIM_OPTIONS_DEFAULT; + + if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* out_options may be NULL */ + + if (!err) { + if (in_index >= in_favorites->count) { + err = kim_error_set_message_for_code (KIM_BAD_IDENTITY_INDEX_ERR, + in_index); + } + } + + if (!err) { + err = kim_identity_copy (&identity, in_favorites->identities[in_index]); + } + + if (!err && in_favorites->options[in_index]) { + err = kim_options_copy (&options, in_favorites->options[in_index]); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + + if (out_options) { + *out_options = options; + options = NULL; + } + } + + kim_identity_free (&identity); + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_favorites_add_identity (kim_favorites io_favorites, + kim_identity in_identity, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_options options = KIM_OPTIONS_DEFAULT; + kim_count insert_at = 0; + + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_options may be KIM_OPTIONS_DEFAULT (NULL) */ + + if (!err) { + err = kim_identity_copy (&identity, in_identity); + } + + if (!err) { + err = kim_options_copy (&options, in_options); + } + + if (!err) { + kim_count i; + + for (i = 0; !err && i < io_favorites->count; i++) { + kim_comparison comparison = 0; + + err = kim_identity_compare (io_favorites->identities[i], + in_identity, + &comparison); + + if (!err) { + if (kim_comparison_is_greater_than (comparison)) { + /* insert before the first entry that is greater than us */ + break; + + } else if (kim_comparison_is_equal_to (comparison)) { + /* already in list */ + kim_string display_string = NULL; + + err = kim_identity_get_display_string (in_identity, + &display_string); + + if (!err) { + err = kim_error_set_message_for_code (KIM_IDENTITY_ALREADY_IN_LIST_ERR, + display_string); + } + + kim_string_free (&display_string); + } + } + } + + insert_at = i; /* Remember where we are going to insert */ + } + + if (!err) { + err = kim_favorites_resize (io_favorites, + io_favorites->count + 1); + } + + if (!err) { + kim_count move_count = io_favorites->count - 1 - insert_at; + + memmove (&io_favorites->identities[insert_at + 1], + &io_favorites->identities[insert_at], + move_count * sizeof (*io_favorites->identities)); + io_favorites->identities[insert_at] = identity; + identity = NULL; + + memmove (&io_favorites->options[insert_at + 1], + &io_favorites->options[insert_at], + move_count * sizeof (*io_favorites->options)); + io_favorites->options[insert_at] = options; + options = NULL; + } + + kim_options_free (&options); + kim_identity_free (&identity); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_favorites_remove_identity (kim_favorites io_favorites, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_boolean found = 0; + kim_count i; + + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + for (i = 0; !err && !found && i < io_favorites->count; i++) { + kim_identity identity = io_favorites->identities[i]; + kim_options options = io_favorites->options[i]; + kim_comparison comparison; + + err = kim_identity_compare (in_identity, identity, &comparison); + + if (!err && kim_comparison_is_equal_to (comparison)) { + kim_error terr = KIM_NO_ERROR; + kim_count new_count = io_favorites->count - 1; + + found = 1; + + memmove (&io_favorites->identities[i], + &io_favorites->identities[i + 1], + (new_count - i) * sizeof (*io_favorites->identities)); + + memmove (&io_favorites->options[i], + &io_favorites->options[i + 1], + (new_count - i) * sizeof (*io_favorites->options)); + + terr = kim_favorites_resize (io_favorites, new_count); + if (terr) { + kim_debug_printf ("failed to resize list to %d. Continuing.", new_count); + } + + kim_options_free (&options); + kim_identity_free (&identity); + } + } + } + + if (!err && !found) { + kim_string display_string = NULL; + + err = kim_identity_get_display_string (in_identity, &display_string); + + if (!err) { + err = kim_error_set_message_for_code (KIM_IDENTITY_NOT_IN_LIST_ERR, + display_string); + } + + kim_string_free (&display_string); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_favorites_remove_all_identities (kim_favorites io_favorites) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_count i; + + for (i = 0; i < io_favorites->count; i++) { + kim_identity_free (&io_favorites->identities[i]); + kim_options_free (&io_favorites->options[i]); + } + free (io_favorites->identities); + free (io_favorites->options); + io_favorites->count = 0; + io_favorites->identities = NULL; + io_favorites->options = NULL; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static void kim_favorites_free (kim_favorites io_favorites) +{ + kim_count i; + + for (i = 0; i < io_favorites->count; i++) { + kim_identity_free (&io_favorites->identities[i]); + kim_options_free (&io_favorites->options[i]); + } + free (io_favorites->identities); + free (io_favorites->options); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_preferences_read (kim_preferences in_preferences) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_options options = NULL; + + err = kim_os_preferences_get_options_for_key (kim_preference_key_options, + &options); + + if (!err) { + kim_options_free (&in_preferences->options); + in_preferences->options = options; + } + } + + if (!err) { + err = kim_os_preferences_get_boolean_for_key (kim_preference_key_remember_options, + kim_default_remember_options, + &in_preferences->remember_options); + } + + if (!err) { + kim_identity default_identity = kim_default_client_identity; + kim_identity identity = NULL; + + err = kim_os_identity_create_for_username (&default_identity); + + if (!err) { + err = kim_os_preferences_get_identity_for_key (kim_preference_key_client_identity, + default_identity, + &identity); + } + + if (!err) { + kim_identity_free (&in_preferences->client_identity); + in_preferences->client_identity = identity; + identity = NULL; + } + + kim_identity_free (&default_identity); + kim_identity_free (&identity); + } + + if (!err) { + err = kim_os_preferences_get_boolean_for_key (kim_preference_key_remember_client_identity, + kim_default_remember_client_identity, + &in_preferences->remember_client_identity); + } + + if (!err) { + struct kim_favorites_opaque favorites = kim_default_favorites; + + err = kim_os_preferences_get_favorites_for_key (kim_preference_key_favorites, + &favorites); + + if (!err) { + kim_favorites_remove_all_identities (&in_preferences->favorites); + in_preferences->favorites = favorites; + } + } + + if (!err) { + err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_minimum_lifetime, + kim_default_minimum_lifetime, + &in_preferences->minimum_lifetime); + } + + if (!err) { + err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_maximum_lifetime, + kim_default_maximum_lifetime, + &in_preferences->maximum_lifetime); + } + + if (!err) { + err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_minimum_renewal_lifetime, + kim_default_minimum_renewal_lifetime, + &in_preferences->minimum_renewal_lifetime); + } + + if (!err) { + err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_maximum_renewal_lifetime, + kim_default_maximum_renewal_lifetime, + &in_preferences->maximum_renewal_lifetime); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_preferences_write (kim_preferences in_preferences) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && in_preferences->options_changed) { + err = kim_os_preferences_set_options_for_key (kim_preference_key_options, + in_preferences->options); + } + + if (!err && in_preferences->remember_options_changed) { + err = kim_os_preferences_set_boolean_for_key (kim_preference_key_remember_options, + in_preferences->remember_options); + } + + if (!err && in_preferences->client_identity_changed) { + kim_identity default_identity = kim_default_client_identity; + + err = kim_os_identity_create_for_username (&default_identity); + + if (!err) { + err = kim_os_preferences_set_identity_for_key (kim_preference_key_client_identity, + in_preferences->client_identity); + } + + kim_identity_free (&default_identity); + } + + if (!err && in_preferences->remember_client_identity_changed) { + err = kim_os_preferences_set_boolean_for_key (kim_preference_key_remember_client_identity, + in_preferences->remember_client_identity); + } + + if (!err && in_preferences->favorites_changed) { + err = kim_os_preferences_set_favorites_for_key (kim_preference_key_favorites, + &in_preferences->favorites); + } + + if (!err && in_preferences->lifetime_range_changed) { + err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_minimum_lifetime, + in_preferences->minimum_lifetime); + if (!err) { + err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_maximum_lifetime, + in_preferences->maximum_lifetime); + } + } + + if (!err && in_preferences->renewal_lifetime_range_changed) { + err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_minimum_renewal_lifetime, + in_preferences->minimum_renewal_lifetime); + if (!err) { + err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_maximum_renewal_lifetime, + in_preferences->maximum_renewal_lifetime); + } + } + + if (!err) { + in_preferences->options_changed = 0; + in_preferences->remember_options_changed = 0; + in_preferences->client_identity_changed = 0; + in_preferences->remember_client_identity_changed = 0; + in_preferences->lifetime_range_changed = 0; + in_preferences->renewal_lifetime_range_changed = 0; + in_preferences->favorites_changed = 0; + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_preferences_allocate (kim_preferences *out_preferences) +{ + kim_error err = kim_library_init (); + kim_preferences preferences = NULL; + + if (!err && !out_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + preferences = malloc (sizeof (*preferences)); + if (!preferences) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *preferences = kim_preferences_initializer; + *out_preferences = preferences; + preferences = NULL; + } + + kim_preferences_free (&preferences); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_create (kim_preferences *out_preferences) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences preferences = NULL; + + if (!err && !out_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_preferences_allocate (&preferences); + } + + if (!err) { + err = kim_preferences_read (preferences); + } + + if (!err) { + *out_preferences = preferences; + preferences = NULL; + } + + kim_preferences_free (&preferences); + + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_copy (kim_preferences *out_preferences, + kim_preferences in_preferences) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences preferences = NULL; + + if (!err && !out_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_preferences_allocate (&preferences); + } + + if (!err) { + preferences->remember_options = in_preferences->remember_options; + err = kim_options_copy (&preferences->options, in_preferences->options); + } + + if (!err) { + preferences->remember_client_identity = in_preferences->remember_client_identity; + err = kim_identity_copy (&preferences->client_identity, in_preferences->client_identity); + } + + if (!err) { + err = kim_favorites_copy (&preferences->favorites, + &in_preferences->favorites); + } + + if (!err) { + *out_preferences = preferences; + preferences = NULL; + } + + kim_preferences_free (&preferences); + + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_options (kim_preferences io_preferences, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = NULL; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_copy (&options, in_options); + } + + if (!err) { + kim_options_free (&io_preferences->options); + io_preferences->options = options; + io_preferences->options_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_options (kim_preferences in_preferences, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_copy (out_options, in_preferences->options); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_remember_options (kim_preferences io_preferences, + kim_boolean in_remember_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->remember_options = in_remember_options; + io_preferences->remember_options_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_remember_options (kim_preferences in_preferences, + kim_boolean *out_remember_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_remember_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_remember_options = in_preferences->remember_options; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_client_identity (kim_preferences io_preferences, + kim_identity in_client_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = KIM_IDENTITY_ANY; + + if (!err && !io_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_client_identity may be KIM_IDENTITY_ANY */ + + if (!err && in_client_identity) { + err = kim_identity_copy (&identity, in_client_identity); + } + + if (!err) { + kim_identity_free (&io_preferences->client_identity); + io_preferences->client_identity = identity; + io_preferences->client_identity_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_client_identity (kim_preferences in_preferences, + kim_identity *out_client_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_copy (out_client_identity, in_preferences->client_identity); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_remember_client_identity (kim_preferences io_preferences, + kim_boolean in_remember_client_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->remember_client_identity = in_remember_client_identity; + io_preferences->remember_client_identity_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_remember_client_identity (kim_preferences in_preferences, + kim_boolean *out_remember_client_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_remember_client_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_remember_client_identity = in_preferences->remember_client_identity; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_minimum_lifetime (kim_preferences io_preferences, + kim_lifetime in_minimum_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->minimum_lifetime = in_minimum_lifetime; + io_preferences->lifetime_range_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_minimum_lifetime (kim_preferences in_preferences, + kim_lifetime *out_minimum_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_minimum_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_minimum_lifetime = in_preferences->minimum_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_maximum_lifetime (kim_preferences io_preferences, + kim_lifetime in_maximum_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->maximum_lifetime = in_maximum_lifetime; + io_preferences->lifetime_range_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_maximum_lifetime (kim_preferences in_preferences, + kim_lifetime *out_maximum_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_maximum_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_maximum_lifetime = in_preferences->maximum_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_minimum_renewal_lifetime (kim_preferences io_preferences, + kim_lifetime in_minimum_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->minimum_renewal_lifetime = in_minimum_renewal_lifetime; + io_preferences->renewal_lifetime_range_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_minimum_renewal_lifetime (kim_preferences in_preferences, + kim_lifetime *out_minimum_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_minimum_renewal_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_minimum_renewal_lifetime = in_preferences->minimum_renewal_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_set_maximum_renewal_lifetime (kim_preferences io_preferences, + kim_lifetime in_maximum_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preferences->maximum_renewal_lifetime = in_maximum_renewal_lifetime; + io_preferences->renewal_lifetime_range_changed = TRUE; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_maximum_renewal_lifetime (kim_preferences in_preferences, + kim_lifetime *out_maximum_renewal_lifetime) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_maximum_renewal_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_maximum_renewal_lifetime = in_preferences->maximum_renewal_lifetime; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_number_of_favorite_identities (kim_preferences in_preferences, + kim_count *out_number_of_identities) +{ + return check_error (kim_favorites_get_number_of_identities (&in_preferences->favorites, + out_number_of_identities)); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_get_favorite_identity_at_index (kim_preferences in_preferences, + kim_count in_index, + kim_identity *out_identity, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* out_options may be NULL */ + + if (!err) { + err = kim_favorites_get_identity_at_index (&in_preferences->favorites, + in_index, + out_identity, + out_options); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_add_favorite_identity (kim_preferences io_preferences, + kim_identity in_identity, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_options may be KIM_OPTIONS_DEFAULT (NULL) */ + + if (!err) { + err = kim_favorites_add_identity (&io_preferences->favorites, + in_identity, in_options); + } + + if (!err) { + io_preferences->favorites_changed = 1; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_remove_favorite_identity (kim_preferences io_preferences, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_favorites_remove_identity (&io_preferences->favorites, + in_identity); + } + + if (!err) { + io_preferences->favorites_changed = 1; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_remove_all_favorite_identities (kim_preferences io_preferences) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_favorites_remove_all_identities (&io_preferences->favorites); + } + + if (!err) { + io_preferences->favorites_changed = 1; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_preferences_synchronize (kim_preferences in_preferences) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_preferences_write (in_preferences); + } + + if (!err) { + err = kim_preferences_read (in_preferences); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_preferences_free (kim_preferences *io_preferences) +{ + if (io_preferences && *io_preferences) { + kim_options_free (&(*io_preferences)->options); + kim_identity_free (&(*io_preferences)->client_identity); + kim_favorites_free (&(*io_preferences)->favorites); + + free (*io_preferences); + *io_preferences = NULL; + } +} + diff --git a/krb5-1-7/src/kim/lib/kim_preferences_private.h b/krb5-1-7/src/kim/lib/kim_preferences_private.h new file mode 100644 index 000000000..239098829 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_preferences_private.h @@ -0,0 +1,126 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_PREFERENCES_PRIVATE_H +#define KIM_PREFERENCES_PRIVATE_H + +#include + +typedef struct kim_favorites_opaque *kim_favorites; + +typedef enum kim_preference_key_enum { + kim_preference_key_options, + kim_preference_key_lifetime, + kim_preference_key_renewable, + kim_preference_key_renewal_lifetime, + kim_preference_key_forwardable, + kim_preference_key_proxiable, + kim_preference_key_addressless, + kim_preference_key_remember_options, + kim_preference_key_client_identity, + kim_preference_key_remember_client_identity, + kim_preference_key_favorites, + kim_preference_key_minimum_lifetime, + kim_preference_key_maximum_lifetime, + kim_preference_key_minimum_renewal_lifetime, + kim_preference_key_maximum_renewal_lifetime +} kim_preference_key; + + +#define kim_default_lifetime 10*60*60 +#define kim_default_renewable TRUE +#define kim_default_renewal_lifetime 7*24*60*60 +#define kim_default_forwardable TRUE +#define kim_default_proxiable TRUE +#define kim_default_addressless TRUE +#define kim_default_remember_options TRUE +#define kim_default_client_identity KIM_IDENTITY_ANY +#define kim_default_remember_client_identity TRUE +#define kim_default_minimum_lifetime 10*60 +#define kim_default_maximum_lifetime 10*60*60 +#define kim_default_minimum_renewal_lifetime 10*60 +#define kim_default_maximum_renewal_lifetime 7*24*60*60 + +extern const struct kim_favorites_opaque kim_default_favorites; + + +/* Helper functions for use by kim_os_preferences_get_favorites_for_key + * and kim_os_preferences_set_favorites_for_key */ + +kim_error kim_favorites_get_number_of_identities (kim_favorites in_favorites, + kim_count *out_number_of_identities); + +kim_error kim_favorites_get_identity_at_index (kim_favorites in_favorites, + kim_count in_index, + kim_identity *out_identity, + kim_options *out_options); + +kim_error kim_favorites_add_identity (kim_favorites io_favorites, + kim_identity in_identity, + kim_options in_options); + +kim_error kim_favorites_remove_identity (kim_favorites io_favorites, + kim_identity in_identity); + +kim_error kim_favorites_remove_all_identities (kim_favorites io_favorites); + + +/* OS-specific functions to be implemented per-platform */ + +kim_error kim_os_preferences_get_options_for_key (kim_preference_key in_key, + kim_options *out_options); + +kim_error kim_os_preferences_set_options_for_key (kim_preference_key in_key, + kim_options in_options); + +kim_error kim_os_preferences_get_identity_for_key (kim_preference_key in_key, + kim_identity in_hardcoded_default, + kim_identity *out_identity); + +kim_error kim_os_preferences_set_identity_for_key (kim_preference_key in_key, + kim_identity in_identity); + +kim_error kim_os_preferences_get_favorites_for_key (kim_preference_key in_key, + kim_favorites io_favorites); + +kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key, + kim_favorites in_favorites); + +kim_error kim_os_preferences_get_lifetime_for_key (kim_preference_key in_key, + kim_lifetime in_hardcoded_default, + kim_lifetime *out_lifetime); + +kim_error kim_os_preferences_set_lifetime_for_key (kim_preference_key in_key, + kim_lifetime in_lifetime); + +kim_error kim_os_preferences_get_boolean_for_key (kim_preference_key in_key, + kim_boolean in_hardcoded_default, + kim_boolean *out_boolean); + +kim_error kim_os_preferences_set_boolean_for_key (kim_preference_key in_key, + kim_boolean in_boolean); + +#endif /* KIM_PREFERENCES_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_private.h b/krb5-1-7/src/kim/lib/kim_private.h new file mode 100644 index 000000000..939279f77 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_private.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_PRIVATE_H +#define KIM_PRIVATE_H + +#include +#include +#include + +#include +#include +#include + +#include "kim_library_private.h" +#include "kim_debug_private.h" +#include "kim_error_private.h" +#include "kim_identity_private.h" +#include "kim_credential_private.h" +#include "kim_options_private.h" +#include "kim_preferences_private.h" +#include "kim_selection_hints_private.h" +#include "kim_string_private.h" +#include "kim_ui_private.h" +#include "kim_ui_gui_private.h" +#include "kim_ui_cli_private.h" +#include "kim_ui_plugin_private.h" + +#endif /* KIM_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_selection_hints.c b/krb5-1-7/src/kim/lib/kim_selection_hints.c new file mode 100644 index 000000000..2b5742830 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_selection_hints.c @@ -0,0 +1,787 @@ +/* + * Copyright 2005-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. + */ + +#include "kim_private.h" + +/* ------------------------------------------------------------------------ */ + +struct kim_selection_hints_opaque { + kim_string application_identifier; + kim_string explanation; + kim_options options; + kim_boolean allow_user_interaction; + kim_boolean use_cached_results; + kim_string service_identity; + kim_string client_realm; + kim_string user; + kim_string service_realm; + kim_string service; + kim_string server; +}; + +struct kim_selection_hints_opaque kim_selection_hints_initializer = { + NULL, + kim_empty_string, + KIM_OPTIONS_DEFAULT, + TRUE, + TRUE, + kim_empty_string, + kim_empty_string, + kim_empty_string, + kim_empty_string, + kim_empty_string, + kim_empty_string +}; + +/* ------------------------------------------------------------------------ */ + +static inline kim_error kim_selection_hints_allocate (kim_selection_hints *out_selection_hints) +{ + kim_error err = kim_library_init (); + kim_selection_hints selection_hints = NULL; + + if (!err && !out_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + selection_hints = malloc (sizeof (*selection_hints)); + if (!selection_hints) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *selection_hints = kim_selection_hints_initializer; + *out_selection_hints = selection_hints; + selection_hints = NULL; + } + + kim_selection_hints_free (&selection_hints); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_create (kim_selection_hints *out_selection_hints, + kim_string in_application_identifier) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints selection_hints = NULL; + + if (!err && !out_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_application_identifier) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_allocate (&selection_hints); + } + + if (!err) { + err = kim_string_copy (&selection_hints->application_identifier, + in_application_identifier); + } + + if (!err) { + *out_selection_hints = selection_hints; + selection_hints = NULL; + } + + kim_selection_hints_free (&selection_hints); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_copy (kim_selection_hints *out_selection_hints, + kim_selection_hints in_selection_hints) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints selection_hints = NULL; + + if (!err && !out_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_allocate (&selection_hints); + } + + if (!err) { + err = kim_string_copy (&selection_hints->application_identifier, + in_selection_hints->application_identifier); + } + + if (!err && in_selection_hints->explanation) { + err = kim_string_copy (&selection_hints->explanation, + in_selection_hints->explanation); + } + + if (!err && in_selection_hints->options) { + err = kim_options_copy (&selection_hints->options, + in_selection_hints->options); + } + + if (!err && in_selection_hints->service_identity) { + err = kim_string_copy (&selection_hints->service_identity, + in_selection_hints->service_identity); + } + + if (!err && in_selection_hints->client_realm) { + err = kim_string_copy (&selection_hints->client_realm, + in_selection_hints->client_realm); + } + + if (!err && in_selection_hints->user) { + err = kim_string_copy (&selection_hints->user, + in_selection_hints->user); + } + + if (!err && in_selection_hints->service_realm) { + err = kim_string_copy (&selection_hints->service_realm, + in_selection_hints->service_realm); + } + + if (!err && in_selection_hints->service) { + err = kim_string_copy (&selection_hints->service, + in_selection_hints->service); + } + + if (!err && in_selection_hints->server) { + err = kim_string_copy (&selection_hints->server, + in_selection_hints->server); + } + + if (!err) { + selection_hints->allow_user_interaction = in_selection_hints->allow_user_interaction; + selection_hints->use_cached_results = in_selection_hints->use_cached_results; + + *out_selection_hints = selection_hints; + selection_hints = NULL; + } + + kim_selection_hints_free (&selection_hints); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_set_hint (kim_selection_hints io_selection_hints, + kim_string in_hint_key, + kim_string in_hint_string) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_hint_key ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_hint_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (!strcmp (in_hint_key, kim_hint_key_client_realm)) { + kim_string_free (&io_selection_hints->client_realm); + err = kim_string_copy (&io_selection_hints->client_realm, + in_hint_string); + + } else if (!strcmp (in_hint_key, kim_hint_key_user)) { + kim_string_free (&io_selection_hints->user); + err = kim_string_copy (&io_selection_hints->user, + in_hint_string); + + } else if (!strcmp (in_hint_key, kim_hint_key_service_realm)) { + kim_string_free (&io_selection_hints->service_realm); + err = kim_string_copy (&io_selection_hints->service_realm, + in_hint_string); + + } else if (!strcmp (in_hint_key, kim_hint_key_service)) { + kim_string_free (&io_selection_hints->service); + err = kim_string_copy (&io_selection_hints->service, + in_hint_string); + + } else if (!strcmp (in_hint_key, kim_hint_key_server)) { + kim_string_free (&io_selection_hints->server); + err = kim_string_copy (&io_selection_hints->server, + in_hint_string); + + } else if (!strcmp (in_hint_key, kim_hint_key_service_identity)) { + kim_string_free (&io_selection_hints->service_identity); + err = kim_string_copy (&io_selection_hints->service_identity, + in_hint_string); + + } else { + err = kim_error_set_message_for_code (KIM_UNSUPPORTED_HINT_ERR, + in_hint_key); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_hint (kim_selection_hints in_selection_hints, + kim_string in_hint_key, + kim_string *out_hint_string) +{ + kim_error err = KIM_NO_ERROR; + kim_string hint = NULL; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_hint_key ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_hint_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (!strcmp (in_hint_key, kim_hint_key_client_realm)) { + hint = in_selection_hints->client_realm; + + } else if (!strcmp (in_hint_key, kim_hint_key_user)) { + hint = in_selection_hints->user; + + } else if (!strcmp (in_hint_key, kim_hint_key_service_realm)) { + hint = in_selection_hints->service_realm; + + } else if (!strcmp (in_hint_key, kim_hint_key_service)) { + hint = in_selection_hints->service; + + } else if (!strcmp (in_hint_key, kim_hint_key_server)) { + hint = in_selection_hints->server; + + } else if (!strcmp (in_hint_key, kim_hint_key_service_identity)) { + hint = in_selection_hints->service_identity; + + } else { + err = kim_error_set_message_for_code (KIM_UNSUPPORTED_HINT_ERR, + in_hint_key); + } + } + + if (!err) { + if (hint && hint != kim_empty_string) { + err = kim_string_copy (out_hint_string, hint); + } else { + *out_hint_string = NULL; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_set_explanation (kim_selection_hints io_selection_hints, + kim_string in_explanation) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_explanation ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_copy (&io_selection_hints->explanation, in_explanation); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_explanation (kim_selection_hints in_selection_hints, + kim_string *out_explanation) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_explanation ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_selection_hints->explanation && + in_selection_hints->explanation != kim_empty_string) { + err = kim_string_copy (out_explanation, in_selection_hints->explanation); + } else { + *out_explanation = NULL; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_application_id (kim_selection_hints in_selection_hints, + kim_string *out_application_id) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_application_id) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_selection_hints->application_identifier) { + err = kim_string_copy (out_application_id, + in_selection_hints->application_identifier); + } else { + *out_application_id = NULL; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_set_options (kim_selection_hints io_selection_hints, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_copy (&io_selection_hints->options, in_options); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_options (kim_selection_hints in_selection_hints, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_copy (out_options, in_selection_hints->options); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_set_allow_user_interaction (kim_selection_hints io_selection_hints, + kim_boolean in_allow_user_interaction) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_selection_hints->allow_user_interaction = in_allow_user_interaction; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_allow_user_interaction (kim_selection_hints in_selection_hints, + kim_boolean *out_allow_user_interaction) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_allow_user_interaction) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_allow_user_interaction = in_selection_hints->allow_user_interaction; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_set_remember_identity (kim_selection_hints io_selection_hints, + kim_boolean in_use_cached_results) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_selection_hints->use_cached_results = in_use_cached_results; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_remember_identity (kim_selection_hints in_selection_hints, + kim_boolean *out_use_cached_results) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_use_cached_results) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + *out_use_cached_results = in_selection_hints->use_cached_results; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_identity (kim_selection_hints in_selection_hints, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_ccache ccache = NULL; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && in_selection_hints->use_cached_results) { + err = kim_os_selection_hints_lookup_identity (in_selection_hints, &identity); + } + + if (!err && !identity && in_selection_hints->allow_user_interaction) { + kim_ui_context context; + + err = kim_ui_init (&context); + + while (!err && !identity) { + kim_boolean user_wants_change_password = 0; + + err = kim_ui_select_identity (&context, + in_selection_hints, + &identity, + &user_wants_change_password); + + if (!err && user_wants_change_password) { + err = kim_identity_change_password_common (identity, 0, + &context, + NULL); + + /* reenter select_identity so just forget this identity + * even if we got an error */ + if (err == KIM_USER_CANCELED_ERR || + err == KIM_DUPLICATE_UI_REQUEST_ERR) { err = KIM_NO_ERROR; } + kim_identity_free (&identity); + } + + } + + if (context.initialized) { + kim_error terr = KIM_NO_ERROR; + terr = kim_ui_fini (&context); + err = (terr != KIM_NO_ERROR) ? terr : err; + } + } + + if (!err) { + *out_identity = identity; + identity = NULL; + } + + kim_identity_free (&identity); + kim_ccache_free (&ccache); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_remember_identity (kim_selection_hints in_selection_hints, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_selection_hints_remember_identity (in_selection_hints, + in_identity); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_forget_identity (kim_selection_hints in_selection_hints) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_selection_hints_forget_identity (in_selection_hints); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_get_preference_strings (kim_selection_hints in_selection_hints, + kim_selection_hints_preference_strings *io_preference_strings) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_preference_strings) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + io_preference_strings->application_identifier = in_selection_hints->application_identifier; + io_preference_strings->service_identity = in_selection_hints->service_identity; + io_preference_strings->client_realm = in_selection_hints->client_realm; + io_preference_strings->user = in_selection_hints->user; + io_preference_strings->service_realm = in_selection_hints->service_realm; + io_preference_strings->service = in_selection_hints->service; + io_preference_strings->server = in_selection_hints->server; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_selection_hints_free (kim_selection_hints *io_selection_hints) +{ + if (io_selection_hints && *io_selection_hints) { + kim_string_free (&(*io_selection_hints)->application_identifier); + kim_string_free (&(*io_selection_hints)->explanation); + kim_options_free (&(*io_selection_hints)->options); + kim_string_free (&(*io_selection_hints)->service_identity); + kim_string_free (&(*io_selection_hints)->client_realm); + kim_string_free (&(*io_selection_hints)->user); + kim_string_free (&(*io_selection_hints)->service_realm); + kim_string_free (&(*io_selection_hints)->service); + kim_string_free (&(*io_selection_hints)->server); + free (*io_selection_hints); + *io_selection_hints = NULL; + } +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_write_to_stream (kim_selection_hints in_selection_hints, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->application_identifier); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->explanation); + } + + if (!err) { + err = kim_options_write_to_stream (in_selection_hints->options, + io_stream); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->service_identity); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->client_realm); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->user); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->service_realm); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->service); + } + + if (!err) { + err = k5_ipc_stream_write_string (io_stream, + in_selection_hints->server); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_read_from_stream (kim_selection_hints io_selection_hints, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + char *application_identifier = NULL; + err = k5_ipc_stream_read_string (io_stream, &application_identifier); + + if (!err) { + err = kim_string_copy (&io_selection_hints->application_identifier, + application_identifier); + } + + k5_ipc_stream_free_string (application_identifier); + } + + if (!err) { + char *explanation = NULL; + err = k5_ipc_stream_read_string (io_stream, &explanation); + + if (!err) { + err = kim_string_copy (&io_selection_hints->explanation, + explanation); + } + + k5_ipc_stream_free_string (explanation); + } + + if (!err) { + if (io_selection_hints->options) { + err = kim_options_read_from_stream (io_selection_hints->options, + io_stream); + } else { + err = kim_options_create_from_stream (&io_selection_hints->options, + io_stream); + } + } + + if (!err) { + char *service_identity = NULL; + err = k5_ipc_stream_read_string (io_stream, &service_identity); + + if (!err) { + err = kim_string_copy (&io_selection_hints->service_identity, + service_identity); + } + + k5_ipc_stream_free_string (service_identity); + } + + if (!err) { + char *client_realm = NULL; + err = k5_ipc_stream_read_string (io_stream, &client_realm); + + if (!err) { + err = kim_string_copy (&io_selection_hints->client_realm, + client_realm); + } + + k5_ipc_stream_free_string (client_realm); + } + + if (!err) { + char *user = NULL; + err = k5_ipc_stream_read_string (io_stream, &user); + + if (!err) { + err = kim_string_copy (&io_selection_hints->user, user); + } + + k5_ipc_stream_free_string (user); + } + + if (!err) { + char *service_realm = NULL; + err = k5_ipc_stream_read_string (io_stream, &service_realm); + + if (!err) { + err = kim_string_copy (&io_selection_hints->service_realm, + service_realm); + } + + k5_ipc_stream_free_string (service_realm); + } + + if (!err) { + char *service = NULL; + err = k5_ipc_stream_read_string (io_stream, &service); + + if (!err) { + err = kim_string_copy (&io_selection_hints->service, service); + } + + k5_ipc_stream_free_string (service); + } + + if (!err) { + char *server = NULL; + err = k5_ipc_stream_read_string (io_stream, &server); + + if (!err) { + err = kim_string_copy (&io_selection_hints->server, server); + } + + k5_ipc_stream_free_string (server); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_selection_hints_create_from_stream (kim_selection_hints *out_selection_hints, + k5_ipc_stream io_stream) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints selection_hints = NULL; + + if (!err && !out_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_allocate (&selection_hints); + } + + if (!err) { + err = kim_selection_hints_read_from_stream (selection_hints, io_stream); + } + + if (!err) { + *out_selection_hints = selection_hints; + selection_hints = NULL; + } + + kim_selection_hints_free (&selection_hints); + + return check_error (err); +} + diff --git a/krb5-1-7/src/kim/lib/kim_selection_hints_private.h b/krb5-1-7/src/kim/lib/kim_selection_hints_private.h new file mode 100644 index 000000000..796116e6a --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_selection_hints_private.h @@ -0,0 +1,66 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_SELECTION_HINTS_PRIVATE_H +#define KIM_SELECTION_HINTS_PRIVATE_H + +#include +#include "k5-ipc_stream.h" + +typedef struct kim_selection_hints_preference_strings { + kim_string application_identifier; + kim_string service_identity; + kim_string client_realm; + kim_string user; + kim_string service_realm; + kim_string service; + kim_string server; +} kim_selection_hints_preference_strings; + +kim_error kim_selection_hints_get_application_id (kim_selection_hints in_selection_hints, + kim_string *out_application_id); + +kim_error kim_selection_hints_get_preference_strings (kim_selection_hints in_selection_hints, + kim_selection_hints_preference_strings *io_preference_strings); + +kim_error kim_os_selection_hints_lookup_identity (kim_selection_hints in_selection_hints, + kim_identity *out_identity); + +kim_error kim_os_selection_hints_remember_identity (kim_selection_hints in_selection_hints, + kim_identity in_identity); + +kim_error kim_os_selection_hints_forget_identity (kim_selection_hints in_selection_hints); + +kim_error kim_selection_hints_write_to_stream (kim_selection_hints in_selection_hints, + k5_ipc_stream io_stream); + +kim_error kim_selection_hints_read_from_stream (kim_selection_hints io_selection_hints, + k5_ipc_stream io_stream); + +kim_error kim_selection_hints_create_from_stream (kim_selection_hints *out_selection_hints, + k5_ipc_stream in_stream); + +#endif /* KIM_SELECTION_HINTS_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_string.c b/krb5-1-7/src/kim/lib/kim_string.c new file mode 100644 index 000000000..8b9af7010 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_string.c @@ -0,0 +1,183 @@ +/* + * $Header$ + * + * 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. + */ + +#include "kim_private.h" + +const char kim_empty_string[1] = ""; + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_from_format (kim_string *out_string, + kim_string in_format, + ...) +{ + kim_error err = kim_library_init (); + va_list args; + + va_start (args, in_format); + err = kim_string_create_from_format_va (out_string, in_format, args); + va_end (args); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_from_format_va_retcode (kim_string *out_string, + kim_string in_format, + va_list in_args) +{ + kim_error err = kim_library_init (); + + int count = vasprintf ((char **) out_string, in_format, in_args); + if (count < 0) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_from_format_va (kim_string *out_string, + kim_string in_format, + va_list in_args) +{ + kim_error err = kim_library_init (); + kim_string string = NULL; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_string_create_from_format_va_retcode (&string, + in_format, + in_args); + } + + if (!err) { + *out_string = string; + string = NULL; + } + + if (string) { kim_string_free (&string); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_from_buffer (kim_string *out_string, + const char *in_buffer, + kim_count in_length) +{ + kim_error err = kim_library_init (); + kim_string string = NULL; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_buffer ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + string = calloc (in_length + 1, sizeof (char *)); + if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + } + + if (!err) { + memcpy ((char *) string, in_buffer, in_length * sizeof (char)); + *out_string = string; + string = NULL; + } + + kim_string_free (&string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_for_last_error (kim_string *out_string, + kim_error in_error) +{ + kim_error err = kim_library_init (); + + err = kim_string_copy (out_string, kim_error_message (in_error)); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_copy (kim_string *out_string, + kim_string in_string) +{ + kim_error err = kim_library_init (); + kim_string string = NULL; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_string[0]) { + string = calloc (strlen (in_string) + 1, sizeof (char *)); + if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + + if (!err) { + strncpy ((char *) string, in_string, strlen (in_string) + 1); + } + } else { + string = kim_empty_string; + } + } + + if (!err) { + *out_string = string; + string = NULL; + } + + kim_string_free (&string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_compare (kim_string in_string, + kim_string in_compare_to_string, + kim_comparison *out_comparison) +{ + return kim_os_string_compare (in_string, + in_compare_to_string, + 0, /* case sensitive */ + out_comparison); +} + +/* ------------------------------------------------------------------------ */ + +void kim_string_free (kim_string *io_string) +{ + if (io_string && *io_string && *io_string != kim_empty_string) { + free ((char *) *io_string); + *io_string = NULL; + } +} diff --git a/krb5-1-7/src/kim/lib/kim_string_private.h b/krb5-1-7/src/kim/lib/kim_string_private.h new file mode 100644 index 000000000..6f4e0ad36 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_string_private.h @@ -0,0 +1,68 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_STRING_PRIVATE_H +#define KIM_STRING_PRIVATE_H + +#include + +extern const char kim_empty_string[1]; + +/* ------------------------------------------------------------------------ */ + +static inline kim_count kim_string_buflen (kim_string in_string) +{ + return in_string ? strlen (in_string) + 1 : 0; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_string_create_from_format (kim_string *out_string, + kim_string in_format, + ...); + +kim_error kim_string_create_from_format_va_retcode (kim_string *out_string, + kim_string in_format, + va_list in_args); + +kim_error kim_string_create_from_format_va (kim_string *out_string, + kim_string in_format, + va_list in_args); + +kim_error kim_string_create_from_buffer (kim_string *out_string, + const char *in_buffer, + kim_count in_length); + +/* OS-specific because it should use UTF8-safe sorting where possible */ +kim_error kim_os_string_compare (kim_string in_string, + kim_string in_compare_to_string, + kim_boolean in_case_insensitive, + kim_comparison *out_comparison); + +kim_error kim_os_string_create_localized (kim_string *out_string, + kim_string in_string); + +#endif /* KIM_STRING_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_ui.c b/krb5-1-7/src/kim/lib/kim_ui.c new file mode 100644 index 000000000..0bac3d819 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui.c @@ -0,0 +1,550 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kim_private.h" + + +/* ------------------------------------------------------------------------ */ + +static kim_prompt_type kim_ui_ptype2ktype (krb5_prompt_type type) +{ + if (type == KRB5_PROMPT_TYPE_PASSWORD) { + return kim_prompt_type_password; + + } else if (type == KRB5_PROMPT_TYPE_PREAUTH) { + return kim_prompt_type_preauth; + } + return kim_prompt_type_preauth; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_ui_init_lazy (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !io_context->initialized) { +#ifdef KIM_BUILTIN_UI + kim_ui_environment environment = kim_library_ui_environment (); + + if (environment == KIM_UI_ENVIRONMENT_GUI) { +#endif /* KIM_BUILTIN_UI */ + io_context->type = kim_ui_type_gui_plugin; + + err = kim_ui_plugin_init (io_context); +#ifdef KIM_BUILTIN_UI + if (err) { + io_context->type = kim_ui_type_gui_builtin; + + err = kim_os_ui_gui_init (io_context); + } + + } else if (environment == KIM_UI_ENVIRONMENT_CLI) { + io_context->type = kim_ui_type_cli; + + err = kim_ui_cli_init (io_context); + + } else { + io_context->type = kim_ui_type_none; + + err = check_error (KIM_NO_UI_ERR); + } +#endif /* KIM_BUILTIN_UI */ + + if (!err) { + io_context->initialized = 1; + } + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_init (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + /* Lazy initialization so we only actually initialize if a prompt + * gets called. This is important because krb5_get_init_creds_* + * can't tell us if a prompt is going to get called in advance */ + io_context->initialized = 0; + io_context->identity = NULL; + io_context->prompt_count = 0; + io_context->password_to_save = NULL; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_init_lazy (in_context); + } + + if (!err) { + if (in_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_enter_identity (in_context, + io_options, + out_identity, + out_change_password); + +#ifdef KIM_BUILTIN_UI + } else if (in_context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_enter_identity (in_context, + io_options, + out_identity, + out_change_password); + + } else if (in_context->type == kim_ui_type_cli) { + err = kim_ui_cli_enter_identity (in_context, + io_options, + out_identity, + out_change_password); + +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_init_lazy (in_context); + } + + if (!err) { + if (in_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_select_identity (in_context, + io_hints, + out_identity, + out_change_password); + +#ifdef KIM_BUILTIN_UI + } else if (in_context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_select_identity (in_context, + io_hints, + out_identity, + out_change_password); + + } else if (in_context->type == kim_ui_type_cli) { + err = kim_ui_cli_select_identity (in_context, + io_hints, + out_identity, + out_change_password); + +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ +/* Set the identity field in your context and pass the context as the data */ + +krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, + void *in_context, + const char *in_name, + const char *in_banner, + int in_num_prompts, + krb5_prompt in_prompts[]) +{ + kim_error err = KIM_NO_ERROR; + krb5_prompt_type *types = NULL; + kim_ui_context *context = (kim_ui_context *) in_context; + int i; + + if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_prompts ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + types = krb5_get_prompt_types (in_krb5_context); + if (!types) { err = check_error (KIM_NULL_PARAMETER_ERR); } + } + + for (i = 0; !err && i < in_num_prompts; i++) { + char *reply = NULL; + kim_prompt_type type = kim_ui_ptype2ktype (types[i]); + kim_boolean got_saved_password = 0; + + if (type == kim_prompt_type_password) { + /* Check for saved password on OSes that support it */ + kim_error terr = KIM_NO_ERROR; + + terr = kim_os_identity_get_saved_password (context->identity, + (kim_string *) &reply); + if (!terr && reply) { got_saved_password = 1; } + } + + if (!got_saved_password) { + kim_boolean save_reply = FALSE; + kim_boolean allow_save_password = kim_os_identity_allow_save_password (); + + context->prompt_count++; + + err = kim_ui_init_lazy (in_context); + + if (!err) { + if (context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_auth_prompt (context, + context->identity, + type, + allow_save_password, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply, + &save_reply); + +#ifdef KIM_BUILTIN_UI + } else if (context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_auth_prompt (context, + context->identity, + type, + allow_save_password, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply, + &save_reply); + + } else if (context->type == kim_ui_type_cli) { + err = kim_ui_cli_auth_prompt (context, + context->identity, + type, + allow_save_password, + in_prompts[i].hidden, + in_name, + in_banner, + in_prompts[i].prompt, + &reply, + &save_reply); +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + if (!err && type == kim_prompt_type_password) { + kim_string_free (&context->password_to_save); + + if (allow_save_password && save_reply) { + err = kim_string_copy (&context->password_to_save, reply); + } + } + } + + if (!err) { + uint32_t reply_len = strlen (reply); + + if ((reply_len + 1) > in_prompts[i].reply->length) { + kim_debug_printf ("%s(): reply %d is too long (is %d, should be %d)\n", + __FUNCTION__, i, + reply_len, in_prompts[i].reply->length); + reply_len = in_prompts[i].reply->length; + } + + memmove (in_prompts[i].reply->data, reply, reply_len + 1); + in_prompts[i].reply->length = reply_len; + } + + /* Clean up reply buffer. Saved passwords are allocated by KIM. */ + if (reply) { + if (got_saved_password) { + memset (reply, '\0', strlen (reply)); + kim_string_free ((kim_string *) &reply); + } else { + kim_ui_free_string (context, &reply); + } + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_init_lazy (in_context); + } + + if (!err) { + if (in_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_change_password (in_context, + in_identity, + in_old_password_expired, + out_old_password, + out_new_password, + out_verify_password); + +#ifdef KIM_BUILTIN_UI + } else if (in_context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_change_password (in_context, + in_identity, + in_old_password_expired, + out_old_password, + out_new_password, + out_verify_password); + + } else if (in_context->type == kim_ui_type_cli) { + err = kim_ui_cli_change_password (in_context, + in_identity, + in_old_password_expired, + out_old_password, + out_new_password, + out_verify_password); +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_init_lazy (in_context); + } + + if (!err) { + if (in_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_handle_error (in_context, + in_identity, + in_error, + in_error_message, + in_error_description); + +#ifdef KIM_BUILTIN_UI + } else if (in_context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_handle_error (in_context, + in_identity, + in_error, + in_error_message, + in_error_description); + + } else if (in_context->type == kim_ui_type_cli) { + err = kim_ui_cli_handle_error (in_context, + in_identity, + in_error, + in_error_message, + in_error_description); +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_ui_free_string (kim_ui_context *in_context, + char **io_string) +{ + kim_error err = kim_ui_init_lazy (in_context); + + if (!err && in_context && io_string && *io_string) { + /* most ui strings are auth information so zero before freeing */ + memset (*io_string, '\0', strlen (*io_string)); + + if (in_context->type == kim_ui_type_gui_plugin) { + kim_ui_plugin_free_string (in_context, + io_string); + +#ifdef KIM_BUILTIN_UI + } else if (in_context->type == kim_ui_type_gui_builtin) { + kim_os_ui_gui_free_string (in_context, + io_string); + + } else if (in_context->type == kim_ui_type_cli) { + kim_ui_cli_free_string (in_context, + io_string); +#endif /* KIM_BUILTIN_UI */ + } + } +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_fini (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && io_context->initialized) { + if (io_context->type == kim_ui_type_gui_plugin) { + err = kim_ui_plugin_fini (io_context); + +#ifdef KIM_BUILTIN_UI + } else if (io_context->type == kim_ui_type_gui_builtin) { + err = kim_os_ui_gui_fini (io_context); + + } else if (io_context->type == kim_ui_type_cli) { + err = kim_ui_cli_fini (io_context); +#endif /* KIM_BUILTIN_UI */ + + } else { + err = check_error (KIM_NO_UI_ERR); + } + + kim_string_free (&io_context->password_to_save); + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ +/* Helper function */ + +kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, + kim_identity in_identity, + enum kim_ui_error_type in_type, + kim_error in_error) +{ + kim_error err = KIM_NO_ERROR; + kim_string message = NULL; + kim_string description = NULL; + + if (!err) { + /* Do this first so last error doesn't get overwritten */ + err = kim_string_create_for_last_error (&description, in_error); + } + + if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_string key = NULL; + + switch (in_type) { + case kim_ui_error_type_authentication: + key = "Kerberos Login Failed:"; + break; + + case kim_ui_error_type_change_password: + key = "Kerberos Change Password Failed:"; + break; + + case kim_ui_error_type_selection: + case kim_ui_error_type_generic: + default: + key = "Kerberos Operation Failed:"; + break; + } + + err = kim_os_string_create_localized (&message, key); + } + + if (!err) { + err = kim_ui_handle_error (in_context, in_identity, + in_error, message, description); + } + + kim_string_free (&description); + kim_string_free (&message); + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/kim_ui_cli.c b/krb5-1-7/src/kim/lib/kim_ui_cli.c new file mode 100644 index 000000000..0bb5eebbb --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_cli.c @@ -0,0 +1,478 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_BUILTIN_UI + +#include "kim_private.h" + +// --------------------------------------------------------------------------- + +static kim_error kim_ui_cli_read_string (kim_string *out_string, + kim_boolean in_hide_reply, + const char *in_format, ...) +{ + kim_error err = KIM_NO_ERROR; + krb5_context k5context = NULL; + krb5_prompt prompts[1]; + char prompt_string [BUFSIZ]; + krb5_data reply_data; + char reply_string [BUFSIZ]; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = krb5_init_context (&k5context); + } + + if (!err) { + unsigned int count; + va_list args; + + va_start (args, in_format); + count = vsnprintf (prompt_string, sizeof (prompt_string), + in_format, args); + va_end (args); + + if (count > sizeof (prompt_string)) { + kim_debug_printf ("%s(): WARNING! Prompt should be %d characters\n", + __FUNCTION__, count); + prompt_string [sizeof (prompt_string) - 1] = '\0'; + } + } + + if (!err) { + /* Build the prompt structures */ + prompts[0].prompt = prompt_string; + prompts[0].hidden = in_hide_reply; + prompts[0].reply = &reply_data; + prompts[0].reply->data = reply_string; + prompts[0].reply->length = sizeof (reply_string); + + err = krb5_prompter_posix (k5context, NULL, NULL, NULL, 1, prompts); + if (err == KRB5_LIBOS_PWDINTR || err == KRB5_LIBOS_CANTREADPWD) { + err = check_error (KIM_USER_CANCELED_ERR); + } + } + + if (!err) { + err = kim_string_create_from_buffer (out_string, + prompts[0].reply->data, + prompts[0].reply->length); + } + + if (k5context) { krb5_free_context (k5context); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_init (kim_ui_context *io_context) +{ + if (io_context) { + io_context->tcontext = NULL; + } + + return KIM_NO_ERROR; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string enter_identity_string = NULL; + kim_string identity_string = NULL; + + if (!err && !io_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_create_localized (&enter_identity_string, + "Please enter your Kerberos identity"); + } + + if (!err) { + err = kim_ui_cli_read_string (&identity_string, + 0, enter_identity_string); + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity_string); + } + + if (!err) { + *out_change_password = 0; + } + + kim_string_free (&identity_string); + kim_string_free (&enter_identity_string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = NULL; + + if (!err && !io_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_get_options (io_hints, &options); + } + + if (!err) { + err = kim_ui_cli_enter_identity (in_context, options, + out_identity, + out_change_password); + } + + if (!err) { + err = kim_selection_hints_set_options (io_hints, options); + } + + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_title, in_message or in_description may be NULL */ + + if (!err) { + if (in_type == kim_prompt_type_password) { + kim_string enter_password_format = NULL; + kim_string identity_string = NULL; + + err = kim_os_string_create_localized (&enter_password_format, + "Please enter the password for %s"); + + if (!err) { + err = kim_identity_get_display_string (in_identity, + &identity_string); + } + + if (!err) { + err = kim_ui_cli_read_string ((kim_string *) out_reply, + 1, enter_password_format, + identity_string); + } + + kim_string_free (&identity_string); + kim_string_free (&enter_password_format); + + } else { + krb5_context k5context = NULL; + krb5_prompt prompts[1]; + krb5_data reply_data; + char reply_string [BUFSIZ]; + + prompts[0].prompt = (char *) in_description; + prompts[0].hidden = in_hide_reply; + prompts[0].reply = &reply_data; + prompts[0].reply->data = reply_string; + prompts[0].reply->length = sizeof (reply_string); + + err = krb5_init_context (&k5context); + + if (!err) { + err = krb5_prompter_posix (k5context, in_context, in_title, + in_message, 1, prompts); + if (err == KRB5_LIBOS_PWDINTR || err == KRB5_LIBOS_CANTREADPWD) { + err = check_error (KIM_USER_CANCELED_ERR); + } + } + + if (!err) { + err = kim_string_create_from_buffer ((kim_string *) out_reply, + prompts[0].reply->data, + prompts[0].reply->length); + if (!err) { + /* always allow password saving */ + *out_save_reply = (in_allow_save_reply && + in_type == kim_prompt_type_password); + } + } + + if (k5context) { krb5_free_context (k5context); } + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_ui_cli_ask_change_password (kim_string in_identity_string) +{ + kim_error err = KIM_NO_ERROR; + kim_string ask_change_password = NULL; + kim_string yes = NULL; + kim_string no = NULL; + kim_string unknown_response = NULL; + kim_boolean done = 0; + kim_comparison no_comparison, yes_comparison; + + if (!err) { + err = kim_os_string_create_localized (&ask_change_password, + "Your password has expired, would you like to change it? (yes/no)"); + } + + if (!err) { + err = kim_os_string_create_localized (&yes, "yes"); + } + + if (!err) { + err = kim_os_string_create_localized (&no, "no"); + } + + if (!err) { + err = kim_os_string_create_localized (&unknown_response, + "%s is not a response I understand. Please try again."); + } + + while (!err && !done) { + kim_string answer = NULL; + + err = kim_ui_cli_read_string (&answer, 0, ask_change_password); + + if (!err) { + err = kim_os_string_compare (answer, no, + 1 /* case insensitive */, + &no_comparison); + } + + if (!err && kim_comparison_is_equal_to (no_comparison)) { + err = check_error (KIM_USER_CANCELED_ERR); + } + + if (!err) { + err = kim_os_string_compare (answer, yes, + 1 /* case insensitive */, + &yes_comparison); + } + + if (!err) { + if (kim_comparison_is_equal_to (yes_comparison)) { + done = 1; + } else { + fprintf (stdout, unknown_response, answer); + fprintf (stdout, "\n"); + } + } + + kim_string_free (&answer); + } + + kim_string_free (&ask_change_password); + kim_string_free (&yes); + kim_string_free (&no); + kim_string_free (&unknown_response); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string enter_old_password_format = NULL; + kim_string enter_new_password_format = NULL; + kim_string enter_verify_password_format = NULL; + kim_string identity_string = NULL; + kim_string old_password = NULL; + kim_string new_password = NULL; + kim_string verify_password = NULL; + kim_boolean done = 0; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_display_string (in_identity, &identity_string); + } + + if (!err && in_old_password_expired) { + err = kim_ui_cli_ask_change_password (identity_string); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_old_password_format, + "Please enter the old password for %s"); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_new_password_format, + "Please enter the new password for %s"); + } + + if (!err) { + err = kim_os_string_create_localized (&enter_verify_password_format, + "Verifying, please re-enter the new password for %s again"); + } + + while (!err && !done) { + kim_boolean was_prompted = 0; /* ignore because we always prompt */ + + kim_string_free (&old_password); + + err = kim_ui_cli_read_string (&old_password, + 1, enter_old_password_format, + identity_string); + + if (!err && strlen (old_password) < 1) { + /* Empty password: Synthesize bad password err */ + err = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + + if (!err) { + err = kim_credential_create_for_change_password ((kim_credential *) &in_context->tcontext, + in_identity, + old_password, + in_context, + &was_prompted); + } + + if (err && err != KIM_USER_CANCELED_ERR) { + /* new creds failed, report error to user */ + err = kim_ui_handle_kim_error (in_context, in_identity, + kim_ui_error_type_change_password, + err); + + } else { + done = 1; + } + } + + if (!err) { + err = kim_ui_cli_read_string (&new_password, + 1, enter_new_password_format, + identity_string); + } + + if (!err) { + err = kim_ui_cli_read_string (&verify_password, + 1, enter_verify_password_format, + identity_string); + } + + if (!err) { + *out_old_password = (char *) old_password; + old_password = NULL; + *out_new_password = (char *) new_password; + new_password = NULL; + *out_verify_password = (char *) verify_password; + verify_password = NULL; + } + + kim_string_free (&old_password); + kim_string_free (&new_password); + kim_string_free (&verify_password); + kim_string_free (&identity_string); + kim_string_free (&enter_old_password_format); + kim_string_free (&enter_new_password_format); + kim_string_free (&enter_verify_password_format); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + fprintf (stdout, "%s\n%s\n\n", in_error_message, in_error_description); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_ui_cli_free_string (kim_ui_context *in_context, + char **io_string) +{ + kim_string_free ((kim_string *) io_string); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_cli_fini (kim_ui_context *io_context) +{ + if (io_context) { + kim_credential_free ((kim_credential *) &io_context->tcontext); + } + + return KIM_NO_ERROR; +} + +#endif /* KIM_BUILTIN_UI */ diff --git a/krb5-1-7/src/kim/lib/kim_ui_cli_private.h b/krb5-1-7/src/kim/lib/kim_ui_cli_private.h new file mode 100644 index 000000000..26970cf79 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_cli_private.h @@ -0,0 +1,80 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_UI_CLI_PRIVATE_H +#define KIM_UI_CLI_PRIVATE_H + +#ifdef KIM_BUILTIN_UI + +#include + +typedef kim_credential kim_ui_cli_context; + + +kim_error kim_ui_cli_init (kim_ui_context *io_context); + +kim_error kim_ui_cli_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_ui_cli_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply); + +kim_error kim_ui_cli_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); + +kim_error kim_ui_cli_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); + +void kim_ui_cli_free_string (kim_ui_context *in_context, + char **io_string); + +kim_error kim_ui_cli_fini (kim_ui_context *in_context); + +#endif /* KIM_BUILTIN_UI */ + +#endif /* KIM_UI_CLI_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_ui_gui_private.h b/krb5-1-7/src/kim/lib/kim_ui_gui_private.h new file mode 100644 index 000000000..ecb324339 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_gui_private.h @@ -0,0 +1,80 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_UI_GUI_PRIVATE_H +#define KIM_UI_GUI_PRIVATE_H + +#ifdef KIM_BUILTIN_UI + +#include + +struct kim_ui_gui_context; +typedef struct kim_ui_gui_context *kim_ui_gui_context; + +kim_error kim_os_ui_gui_init (kim_ui_context *io_context); + +kim_error kim_os_ui_gui_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply); + +kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); + +kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); + +void kim_os_ui_gui_free_string (kim_ui_context *in_context, + char **io_string); + +kim_error kim_os_ui_gui_fini (kim_ui_context *in_context); + +#endif /* KIM_BUILTIN_UI */ + +#endif /* KIM_UI_GUI_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_ui_plugin.c b/krb5-1-7/src/kim/lib/kim_ui_plugin.c new file mode 100644 index 000000000..c307dd189 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_plugin.c @@ -0,0 +1,354 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kim_private.h" + + +const char * const *kim_ui_plugin_files = NULL; +#if TARGET_OS_MAC +static const char *kim_ui_plugin_dirs[] = { KRB5_KIM_UI_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/kimui", NULL }; +#else +static const char *kim_ui_plugin_dirs[] = { LIBDIR "/krb5/plugins/kimui", NULL }; +#endif + + +struct kim_ui_plugin_context { + krb5_context kcontext; + struct plugin_dir_handle plugins; + struct kim_ui_plugin_ftable_v0 *ftable; + void **ftables; + void *plugin_context; +}; + + +/* ------------------------------------------------------------------------ */ + +static void kim_ui_plugin_context_free (kim_ui_plugin_context *io_context) +{ + if (io_context && *io_context) { + if ((*io_context)->ftables) { + krb5int_free_plugin_dir_data ((*io_context)->ftables); + } + if (PLUGIN_DIR_OPEN (&(*io_context)->plugins)) { + krb5int_close_plugin_dirs (&(*io_context)->plugins); + } + if ((*io_context)->kcontext) { + krb5_free_context ((*io_context)->kcontext); + } + free (*io_context); + *io_context = NULL; + } +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_ui_plugin_context_allocate (kim_ui_plugin_context *out_context) +{ + kim_error err = KIM_NO_ERROR; + kim_ui_plugin_context context = NULL; + + if (!err && !out_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + context = malloc (sizeof (*context)); + if (!context) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + err = krb5_error (NULL, krb5_init_context (&context->kcontext)); + } + + if (!err) { + PLUGIN_DIR_INIT(&context->plugins); + context->ftable = NULL; + context->ftables = NULL; + context->plugin_context = NULL; + + *out_context = context; + context = NULL; + } + + kim_ui_plugin_context_free (&context); + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_init (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + kim_ui_plugin_context context = NULL; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_ui_plugin_context_allocate (&context); + } + + if (!err) { + PLUGIN_DIR_INIT(&context->plugins); + + err = krb5_error (context->kcontext, + krb5int_open_plugin_dirs (kim_ui_plugin_dirs, + kim_ui_plugin_files, + &context->plugins, + &context->kcontext->err)); + } + + if (!err) { + err = krb5_error (context->kcontext, + krb5int_get_plugin_dir_data (&context->plugins, + "kim_ui_0", + &context->ftables, + &context->kcontext->err)); + } + + if (!err && context->ftables) { + int i; + + for (i = 0; context->ftables[i]; i++) { + struct kim_ui_plugin_ftable_v0 *ftable = context->ftables[i]; + context->plugin_context = NULL; + + err = ftable->init (&context->plugin_context); + + if (!err) { + context->ftable = ftable; + break; /* use first plugin that initializes correctly */ + } + + err = KIM_NO_ERROR; /* ignore failed plugins */ + } + } + + if (!err && !context->ftable) { + err = check_error (KRB5_PLUGIN_NO_HANDLE); + } + + if (!err) { + io_context->tcontext = context; + context = NULL; + } + + kim_ui_plugin_context_free (&context); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + err = context->ftable->enter_identity (context->plugin_context, + io_options, + out_identity, + out_change_password); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + err = context->ftable->select_identity (context->plugin_context, + io_hints, + out_identity, + out_change_password); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_title, in_message or in_description may be NULL */ + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + err = context->ftable->auth_prompt (context->plugin_context, + in_identity, + in_type, + in_allow_save_reply, + in_hide_reply, + in_title, + in_message, + in_description, + out_reply, + out_save_reply); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + err = context->ftable->change_password (context->plugin_context, + in_identity, + in_old_password_expired, + out_old_password, + out_new_password, + out_verify_password); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + err = context->ftable->handle_error (context->plugin_context, + in_identity, + in_error, + in_error_message, + in_error_description); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_ui_plugin_free_string (kim_ui_context *in_context, + char **io_string) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) in_context->tcontext; + + context->ftable->free_string (context->plugin_context, + io_string); + } + } + +/* ------------------------------------------------------------------------ */ + +kim_error kim_ui_plugin_fini (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_ui_plugin_context context = (kim_ui_plugin_context) io_context->tcontext; + + if (context) { + err = context->ftable->fini (context->plugin_context); + } + + if (!err) { + kim_ui_plugin_context_free (&context); + io_context->tcontext = NULL; + } + } + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/kim_ui_plugin_private.h b/krb5-1-7/src/kim/lib/kim_ui_plugin_private.h new file mode 100644 index 000000000..397a7ad91 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_plugin_private.h @@ -0,0 +1,77 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_UI_PLUGIN_PRIVATE_H +#define KIM_UI_PLUGIN_PRIVATE_H + +#include + +struct kim_ui_plugin_context; +typedef struct kim_ui_plugin_context *kim_ui_plugin_context; + + +kim_error kim_ui_plugin_init (kim_ui_context *io_context); + +kim_error kim_ui_plugin_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_ui_plugin_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_ui_plugin_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply); + +kim_error kim_ui_plugin_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); + +kim_error kim_ui_plugin_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); + +void kim_ui_plugin_free_string (kim_ui_context *in_context, + char **io_string); + +kim_error kim_ui_plugin_fini (kim_ui_context *in_context); + +#endif /* KIM_UI_PLUGIN_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/kim_ui_private.h b/krb5-1-7/src/kim/lib/kim_ui_private.h new file mode 100644 index 000000000..b0a92dc99 --- /dev/null +++ b/krb5-1-7/src/kim/lib/kim_ui_private.h @@ -0,0 +1,101 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_UI_PRIVATE_H +#define KIM_UI_PRIVATE_H + +#include + +enum kim_ui_type { + kim_ui_type_gui_plugin, + kim_ui_type_gui_builtin, + kim_ui_type_cli, + kim_ui_type_none +}; + +enum kim_ui_error_type { + kim_ui_error_type_authentication, + kim_ui_error_type_change_password, + kim_ui_error_type_selection, + kim_ui_error_type_generic +}; + +/* declare struct on stack. Deep contents will be freed by kim_ui_fini. */ +typedef struct kim_ui_context { + kim_boolean initialized; + enum kim_ui_type type; + void *tcontext; + kim_identity identity; + kim_count prompt_count; + kim_string password_to_save; +} kim_ui_context; + + + +kim_error kim_ui_init (kim_ui_context *io_context); + +kim_error kim_ui_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password); + +kim_error kim_ui_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password); + +krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, + void *in_context, + const char *in_name, + const char *in_banner, + int in_num_prompts, + krb5_prompt in_prompts[]); + +kim_error kim_ui_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password); + +/* Helper function */ +kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, + kim_identity in_identity, + enum kim_ui_error_type in_type, + kim_error in_error); + +kim_error kim_ui_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description); + +void kim_ui_free_string (kim_ui_context *in_context, + char **io_string); + +kim_error kim_ui_fini (kim_ui_context *io_context); + +#endif /* KIM_UI_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/mac/KerberosLogin.c b/krb5-1-7/src/kim/lib/mac/KerberosLogin.c new file mode 100644 index 000000000..de05e57dd --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/KerberosLogin.c @@ -0,0 +1,1860 @@ +/* + * $Header$ + * + * 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. + */ + +#ifdef KIM_TO_KLL_SHIM + +#include "CredentialsCache.h" +#include "KerberosLogin.h" +#include "KerberosLoginPrivate.h" +#include +#include "kim_private.h" +#include "k5-thread.h" +#include + +/* + * Deprecated Error codes + */ +enum { + /* Carbon Dialog errors */ + klDialogDoesNotExistErr = 19676, + klDialogAlreadyExistsErr, + klNotInForegroundErr, + klNoAppearanceErr, + klFatalDialogErr, + klCarbonUnavailableErr +}; + +krb5_get_init_creds_opt *__KLLoginOptionsGetKerberos5Options (KLLoginOptions ioOptions); +KLTime __KLLoginOptionsGetStartTime (KLLoginOptions ioOptions); +char *__KLLoginOptionsGetServiceName (KLLoginOptions ioOptions); + + +/* ------------------------------------------------------------------------ */ + +static KLStatus kl_check_error_ (kim_error inError, const char *function, const char *file, int line) +{ + kim_error err = inError; + + switch (err) { + case ccNoError: + err = klNoErr; + break; + + case ccErrBadName: + err = klPrincipalDoesNotExistErr; + break; + + case ccErrCCacheNotFound: + err = klCacheDoesNotExistErr; + break; + + case ccErrCredentialsNotFound: + err = klNoCredentialsErr; + break; + + case KIM_OUT_OF_MEMORY_ERR: + case ccErrNoMem: + err = klMemFullErr; + break; + + case ccErrBadCredentialsVersion: + err = klInvalidVersionErr; + break; + + case KIM_NULL_PARAMETER_ERR: + case ccErrBadParam: + case ccIteratorEnd: + case ccErrInvalidContext: + case ccErrInvalidCCache: + case ccErrInvalidString: + case ccErrInvalidCredentials: + case ccErrInvalidCCacheIterator: + case ccErrInvalidCredentialsIterator: + case ccErrInvalidLock: + case ccErrBadAPIVersion: + case ccErrContextLocked: + case ccErrContextUnlocked: + case ccErrCCacheLocked: + case ccErrCCacheUnlocked: + case ccErrBadLockType: + case ccErrNeverDefault: + err = klParameterErr; + break; + + case KIM_USER_CANCELED_ERR: + case KRB5_LIBOS_PWDINTR: + err = klUserCanceledErr; + break; + } + + if (err) { + kim_debug_printf ("%s() remapped %d to %d ('%s') at %s: %d", + function, inError, err, kim_error_message (err), + file, line); + } + + return err; +} +#define kl_check_error(err) kl_check_error_(err, __FUNCTION__, __FILE__, __LINE__) + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireTickets (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + return kl_check_error (KLAcquireInitialTickets (inPrincipal, + NULL, + outPrincipal, + outCredCacheName)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewTickets (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + return kl_check_error (KLAcquireNewInitialTickets (inPrincipal, + NULL, + outPrincipal, + outCredCacheName)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) +{ + return kl_check_error (KLAcquireInitialTicketsWithPassword (inPrincipal, + inLoginOptions, + inPassword, + outCredCacheName)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) +{ + return kl_check_error (KLAcquireNewInitialTicketsWithPassword (inPrincipal, + inLoginOptions, + inPassword, + outCredCacheName)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetApplicationOptions (const void *inAppOptions) +{ + /* Deprecated */ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetApplicationOptions (void *outAppOptions) +{ + /* Deprecated -- this function took a struct declared on the caller's + * stack. It used to fill in the struct with information about the + * Mac OS 9 dialog used for automatic prompting. Since there is no + * way for us provide valid values, just leave the struct untouched + * and return a reasonable error. */ + return kl_check_error (klDialogDoesNotExistErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_string name = NULL; + kim_identity identity = NULL; + + if (!err) { + err = kim_ccache_create_new_if_needed (&ccache, + inPrincipal, + inLoginOptions); + } + + if (!err && outPrincipal) { + err = kim_ccache_get_client_identity (ccache, &identity); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, &name); + } + + if (!err) { + if (outPrincipal) { + *outPrincipal = identity; + identity = NULL; + } + if (outCredCacheName) { + *outCredCacheName = (char *) name; + name = NULL; + } + } + + kim_string_free (&name); + kim_identity_free (&identity); + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_string name = NULL; + kim_identity identity = NULL; + + err = kim_ccache_create_new (&ccache, inPrincipal, inLoginOptions); + + if (!err && outPrincipal) { + err = kim_ccache_get_client_identity (ccache, &identity); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, &name); + } + + if (!err) { + if (outPrincipal) { + *outPrincipal = identity; + identity = NULL; + } + if (outCredCacheName) { + *outCredCacheName = (char *) name; + name = NULL; + } + } + + kim_string_free (&name); + kim_identity_free (&identity); + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLDestroyTickets (KLPrincipal inPrincipal) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err) { + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + } + + if (!err) { + err = kim_ccache_destroy (&ccache); + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLChangePassword (KLPrincipal inPrincipal) +{ + return kl_check_error (kim_identity_change_password (inPrincipal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireInitialTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err) { + err = kim_ccache_create_new_if_needed_with_password (&ccache, + inPrincipal, + inLoginOptions, + inPassword); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewInitialTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + err = kim_ccache_create_new_with_password (&ccache, + inPrincipal, + inLoginOptions, + inPassword); + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewInitialTicketCredentialsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + krb5_context inV5Context, + KLBoolean *outGotV4Credentials, + KLBoolean *outGotV5Credentials, + void *outV4Credentials, + krb5_creds *outV5Credentials) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + krb5_creds *creds = NULL; + + if (!err) { + err = kim_credential_create_new_with_password (&credential, + inPrincipal, + inLoginOptions, + inPassword); + } + + if (!err) { + err = kim_credential_get_krb5_creds (credential, + inV5Context, + &creds); + } + + if (!err) { + *outGotV5Credentials = 1; + *outGotV4Credentials = 0; + *outV5Credentials = *creds; + free (creds); /* eeeew */ + creds = NULL; + } + + kim_credential_free (&credential); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLStoreNewInitialTicketCredentials (KLPrincipal inPrincipal, + krb5_context inV5Context, + void *inV4Credentials, + krb5_creds *inV5Credentials, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_ccache ccache = NULL; + + err = kim_credential_create_from_krb5_creds (&credential, + inV5Context, + inV5Credentials); + + if (!err) { + err = kim_credential_store (credential, inPrincipal, &ccache); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + kim_credential_free (&credential); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLVerifyInitialTickets (KLPrincipal inPrincipal, + KLBoolean inFailIfNoHostKey, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + + if (!err) { + err = kim_ccache_verify (ccache, + KIM_IDENTITY_ANY, + NULL, + inFailIfNoHostKey); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLVerifyInitialTicketCredentials (void *inV4Credentials, + krb5_creds *inV5Credentials, + KLBoolean inFailIfNoHostKey) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + krb5_context context = NULL; + + err = krb5_error (NULL, krb5_init_context (&context)); + + if (!err) { + err = kim_credential_create_from_krb5_creds (&credential, + context, + inV5Credentials); + } + + if (!err) { + err = kim_credential_verify (credential, KIM_IDENTITY_ANY, + NULL, inFailIfNoHostKey); + } + + if (context) { krb5_free_context (context); } + kim_credential_free (&credential); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLAcquireNewInitialTicketsWithKeytab (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inKeytabName, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + err = kim_ccache_create_from_keytab (&ccache, + inPrincipal, + inLoginOptions, + inKeytabName); + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLRenewInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_string name = NULL; + kim_identity identity = NULL; + + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + + if (!err) { + err = kim_ccache_renew (ccache, inLoginOptions); + } + + if (!err && outPrincipal) { + err = kim_ccache_get_client_identity (ccache, &identity); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, &name); + } + + if (!err) { + if (outPrincipal) { + *outPrincipal = identity; + identity = NULL; + } + if (outCredCacheName) { + *outCredCacheName = (char *) name; + name = NULL; + } + } + + kim_string_free (&name); + kim_identity_free (&identity); + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLValidateInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + + if (!err) { + err = kim_ccache_validate (ccache, inLoginOptions); + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, + (kim_string *) outCredCacheName); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +static cc_time_t g_cc_change_time = 0; +static KLTime g_kl_change_time = 0; +static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +MAKE_INIT_FUNCTION(kim_change_time_init); +MAKE_FINI_FUNCTION(kim_change_time_fini); + +/* ------------------------------------------------------------------------ */ + +static int kim_change_time_init (void) +{ + g_kl_change_time = time (NULL); + + return k5_mutex_finish_init(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ + +static void kim_change_time_fini (void) +{ + if (!INITIALIZER_RAN (kim_change_time_init) || PROGRAM_EXITING ()) { + return; + } + + k5_mutex_destroy(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLastChangedTime (KLTime *outLastChangedTime) +{ + KLStatus err = CALL_INIT_FUNCTION (kim_change_time_init); + kim_error mutex_err = KIM_NO_ERROR; + cc_context_t context = NULL; + cc_time_t ccChangeTime = 0; + + if (!err && !outLastChangedTime) { err = kl_check_error (klParameterErr); } + + if (!err) { + mutex_err = k5_mutex_lock (&g_change_time_mutex); + if (mutex_err) { err = mutex_err; } + } + + if (!err) { + err = cc_initialize (&context, ccapi_version_4, NULL, NULL); + } + + if (!err) { + err = cc_context_get_change_time (context, &ccChangeTime); + } + + if (!err) { + /* cc_context_get_change_time returns 0 if there are no tickets + * but KLLastChangedTime always returned the current time. So + * fake the current time if cc_context_get_change_time returns 0. */ + if (ccChangeTime > g_cc_change_time) { + /* changed, make sure g_kl_change_time increases in value */ + if (ccChangeTime > g_kl_change_time) { + g_kl_change_time = ccChangeTime; + } else { + g_kl_change_time++; /* we got ahead of the ccapi, just increment */ + } + g_cc_change_time = ccChangeTime; + } + + *outLastChangedTime = g_kl_change_time; + } + + if (context ) { cc_context_release (context); } + if (!mutex_err) { k5_mutex_unlock (&g_change_time_mutex); } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLCacheHasValidTickets (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLBoolean *outFoundValidTickets, + KLPrincipal *outPrincipal, + char **outCredCacheName) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_credential_state state = kim_credentials_state_valid; + kim_identity identity = NULL; + kim_string name = NULL; + + if (!outFoundValidTickets) { err = kl_check_error (klParameterErr); } + + if (!err) { + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + } + + if (!err) { + err = kim_ccache_get_state (ccache, &state); + } + + if (!err && outPrincipal) { + err = kim_ccache_get_client_identity (ccache, &identity); + if (err) { + err = KIM_NO_ERROR; + identity = NULL; + } + } + + if (!err && outCredCacheName) { + err = kim_ccache_get_display_name (ccache, &name); + } + + if (!err) { + *outFoundValidTickets = (state == kim_credentials_state_valid); + if (outPrincipal) { + *outPrincipal = identity; + identity = NULL; + } + if (outCredCacheName) { + *outCredCacheName = (char *) name; + name = NULL; + } + } + + kim_string_free (&name); + kim_identity_free (&identity); + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLTicketStartTime (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLTime *outStartTime) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_time start_time = 0; + + if (!err) { + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + } + + if (!err) { + err = kim_ccache_get_start_time (ccache, &start_time); + } + + if (!err) { + *outStartTime = start_time; + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLTicketExpirationTime (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLTime *outExpirationTime) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + kim_time expiration_time = 0; + + if (!err) { + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + } + + if (!err) { + err = kim_ccache_get_expiration_time (ccache, &expiration_time); + } + + if (!err) { + *outExpirationTime = expiration_time; + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetSystemDefaultCache (KLPrincipal inPrincipal) +{ + kim_error err = KIM_NO_ERROR; + kim_ccache ccache = NULL; + + if (!err) { + err = kim_ccache_create_from_client_identity (&ccache, inPrincipal); + } + + if (!err) { + err = kim_ccache_set_default (ccache); + } + + kim_ccache_free (&ccache); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLHandleError (KLStatus inError, + KLDialogIdentifier inDialogIdentifier, + KLBoolean inShowAlert) +{ + kim_error err = KIM_NO_ERROR; + kim_ui_context context; + kim_boolean ui_inited = 0; + + if (!err) { + err = kim_ui_init (&context); + if (!err) { ui_inited = 1; } + } + + if (!err) { + int type = kim_ui_error_type_generic; + + switch (inDialogIdentifier) { + case loginLibrary_LoginDialog: + type = kim_ui_error_type_authentication; + break; + case loginLibrary_ChangePasswordDialog: + type = kim_ui_error_type_change_password; + break; + default: + type = kim_ui_error_type_generic; + break; + } + + err = kim_ui_handle_kim_error (&context, + KIM_IDENTITY_ANY, type, inError); + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = kl_check_error (fini_err); } + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetErrorString (KLStatus inError, + char **outErrorString) +{ + return kl_check_error (kim_string_create_for_last_error ((kim_string *) outErrorString, + inError)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLCancelAllDialogs (void) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +/* Kerberos change password dialog low level functions */ + +KLStatus KLChangePasswordWithPasswords (KLPrincipal inPrincipal, + const char *inOldPassword, + const char *inNewPassword, + KLBoolean *outRejected, + char **outRejectionError, + char **outRejectionDescription) +{ + kim_error err = KIM_NO_ERROR; + kim_credential credential = NULL; + kim_ui_context context; + kim_boolean ui_inited = 0; + kim_error rejected_err = KIM_NO_ERROR; + kim_string rejected_message = NULL; + kim_string rejected_description = NULL; + + if (!inOldPassword) { err = kl_check_error (klParameterErr); } + if (!inNewPassword) { err = kl_check_error (klParameterErr); } + if (!outRejected ) { err = kl_check_error (klParameterErr); } + + if (!err) { + err = kim_ui_init (&context); + if (!err) { ui_inited = 1; } + } + + if (!err) { + kim_boolean was_prompted = 0; + + err = kim_credential_create_for_change_password (&credential, + inPrincipal, + inOldPassword, + &context, + &was_prompted); + } + + if (!err) { + err = kim_identity_change_password_with_credential (inPrincipal, + credential, + inNewPassword, + &context, + &rejected_err, + &rejected_message, + &rejected_description); + } + + if (!err) { + *outRejected = (rejected_err != 0); + if (rejected_err) { + if (outRejectionError) { + *outRejectionError = (char *) rejected_message; + rejected_message = NULL; + } + if (outRejectionDescription) { + *outRejectionDescription = (char *) rejected_description; + rejected_description = NULL; + } + } + } + + if (ui_inited) { + kim_error fini_err = kim_ui_fini (&context); + if (!err) { err = kl_check_error (fini_err); } + } + + kim_string_free (&rejected_message); + kim_string_free (&rejected_description); + kim_credential_free (&credential); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +/* Application Configuration functions */ + +KLStatus KLSetIdleCallback (const KLIdleCallback inCallback, + const KLRefCon inRefCon) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetIdleCallback (KLIdleCallback* inCallback, + KLRefCon* inRefCon) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +/* Library configuration functions */ +/* Deprecated options which we now ignore */ +enum { + loginOption_ShowOptions = 'sopt', + loginOption_RememberShowOptions = 'ropt', + loginOption_LongTicketLifetimeDisplay = 'hms ', + loginOption_RememberPassword = 'pass' +}; + + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetDefaultLoginOption (const KLDefaultLoginOption inOption, + void *ioBuffer, + KLSize *ioBufferSize) +{ + KLStatus err = klNoErr; + kim_preferences prefs = NULL; + KLSize targetSize = 0; + KLBoolean returnSizeOnly = (ioBuffer == NULL); + + if (!ioBufferSize) { err = kl_check_error (klParameterErr); } + + if (!err) { + err = kim_preferences_create (&prefs); + } + + if (!err && inOption == loginOption_LoginName) { + kim_identity identity = NULL; + kim_string string = ""; + + err = kim_preferences_get_client_identity (prefs, &identity); + + if (!err && identity) { + err = kim_identity_get_components_string (identity, &string); + } + + if (!err) { + targetSize = strlen (string); + if (!returnSizeOnly) { + if (*ioBufferSize < targetSize) { + err = kl_check_error (klBufferTooSmallErr); + } else if (targetSize > 0) { + memmove (ioBuffer, string, targetSize); + } + } + } + + if (string && string[0]) { kim_string_free (&string); } + + } else if (!err && inOption == loginOption_LoginInstance) { + targetSize = 0; /* Deprecated */ + + } else if (!err && (inOption == loginOption_ShowOptions || + inOption == loginOption_RememberShowOptions || + inOption == loginOption_LongTicketLifetimeDisplay || + inOption == loginOption_RememberPrincipal || + inOption == loginOption_RememberExtras || + inOption == loginOption_RememberPassword)) { + targetSize = sizeof(KLBoolean); + + if (!returnSizeOnly) { + kim_boolean boolean = 0; + + if (inOption == loginOption_ShowOptions || + inOption == loginOption_RememberShowOptions || + inOption == loginOption_LongTicketLifetimeDisplay) { + boolean = 1; /* Deprecated */ + + } else if (inOption == loginOption_RememberPrincipal) { + err = kim_preferences_get_remember_client_identity (prefs, &boolean); + + } else if (inOption == loginOption_RememberExtras) { + err = kim_preferences_get_remember_options (prefs, &boolean); + + } else if (inOption == loginOption_RememberPassword) { + boolean = kim_os_identity_allow_save_password (); + } + + if (!err) { + if (*ioBufferSize < targetSize) { + err = kl_check_error (klBufferTooSmallErr); + } else { + *(KLBoolean *)ioBuffer = boolean; + } + } + } + + } else if (!err && (inOption == loginOption_MinimalTicketLifetime || + inOption == loginOption_MaximalTicketLifetime || + inOption == loginOption_MinimalRenewableLifetime || + inOption == loginOption_MaximalRenewableLifetime)) { + targetSize = sizeof(KLLifetime); + + if (!returnSizeOnly) { + kim_lifetime lifetime = 0; + + if (inOption == loginOption_MinimalTicketLifetime) { + err = kim_preferences_get_minimum_lifetime (prefs, &lifetime); + + } else if (inOption == loginOption_MaximalTicketLifetime) { + err = kim_preferences_get_maximum_lifetime (prefs, &lifetime); + + } else if (inOption == loginOption_MinimalRenewableLifetime) { + err = kim_preferences_get_minimum_renewal_lifetime (prefs, &lifetime); + + } else if (inOption == loginOption_MaximalRenewableLifetime) { + err = kim_preferences_get_maximum_renewal_lifetime (prefs, &lifetime); + } + + if (!err) { + if (*ioBufferSize < targetSize) { + err = kl_check_error (klBufferTooSmallErr); + } else { + *(KLLifetime *)ioBuffer = lifetime; + } + } + } + + } else if (!err && (inOption == loginOption_DefaultRenewableTicket || + inOption == loginOption_DefaultForwardableTicket || + inOption == loginOption_DefaultProxiableTicket || + inOption == loginOption_DefaultAddresslessTicket)) { + targetSize = sizeof(KLBoolean); + + if (!returnSizeOnly) { + kim_options options = NULL; + kim_boolean boolean = 0; + + err = kim_preferences_get_options (prefs, &options); + + if (!err && inOption == loginOption_DefaultRenewableTicket) { + err = kim_options_get_renewable (options, &boolean); + + } else if (!err && inOption == loginOption_DefaultForwardableTicket) { + err = kim_options_get_forwardable (options, &boolean); + + } else if (!err && inOption == loginOption_DefaultProxiableTicket) { + err = kim_options_get_proxiable (options, &boolean); + + } else if (!err && inOption == loginOption_DefaultAddresslessTicket) { + err = kim_options_get_addressless (options, &boolean); + } + + if (!err) { + if (*ioBufferSize < targetSize) { + err = kl_check_error (klBufferTooSmallErr); + } else { + *(KLBoolean *)ioBuffer = boolean; + } + } + + kim_options_free (&options); + } + + + } else if (!err && (inOption == loginOption_DefaultTicketLifetime || + inOption == loginOption_DefaultRenewableLifetime)) { + targetSize = sizeof(KLLifetime); + + if (!returnSizeOnly) { + kim_options options = NULL; + kim_lifetime lifetime = 0; + + err = kim_preferences_get_options (prefs, &options); + + if (!err && inOption == loginOption_DefaultTicketLifetime) { + err = kim_options_get_lifetime (options, &lifetime); + + } else if (!err && inOption == loginOption_DefaultRenewableLifetime) { + err = kim_options_get_renewal_lifetime (options, &lifetime); + } + + if (!err) { + if (*ioBufferSize < targetSize) { + err = kl_check_error (klBufferTooSmallErr); + } else { + *(KLLifetime *)ioBuffer = lifetime; + } + } + + kim_options_free (&options); + } + + } else { + err = kl_check_error (klInvalidOptionErr); + } + + if (!err) { + *ioBufferSize = targetSize; + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetDefaultLoginOption (const KLDefaultLoginOption inOption, + const void *inBuffer, + const KLSize inBufferSize) +{ + KLStatus err = klNoErr; + kim_preferences prefs = NULL; + + if (inBuffer == NULL) { err = kl_check_error (klParameterErr); } + if (inBufferSize < 0) { err = kl_check_error (klParameterErr); } + + if (!err) { + err = kim_preferences_create (&prefs); + } + + if (!err && inOption == loginOption_LoginName) { + kim_identity old_identity = NULL; + kim_identity new_identity = NULL; + kim_string new_identity_string = NULL; + kim_string realm = NULL; + kim_string components = NULL; + + err = kim_string_create_from_buffer (&components, inBuffer, inBufferSize); + + if (!err) { + err = kim_preferences_get_client_identity (prefs, &old_identity); + + if (!err && old_identity) { + err = kim_identity_get_realm (old_identity, &realm); + } + } + + if (!err && realm) { + err = kim_string_create_from_format (&new_identity_string, + "%s@%s", components, realm); + } + + if (!err) { + err = kim_identity_create_from_string (&new_identity, + (new_identity_string ? + new_identity_string : + components)); + } + + if (!err) { + err = kim_preferences_set_client_identity (prefs, new_identity); + } + + kim_string_free (&components); + kim_string_free (&realm); + kim_string_free (&new_identity_string); + kim_identity_free (&old_identity); + kim_identity_free (&new_identity); + + } else if (!err && inOption == loginOption_LoginInstance) { + /* Ignored */ + + } else if (!err && (inOption == loginOption_ShowOptions || + inOption == loginOption_RememberShowOptions || + inOption == loginOption_LongTicketLifetimeDisplay || + inOption == loginOption_RememberPrincipal || + inOption == loginOption_RememberExtras || + inOption == loginOption_RememberPassword)) { + if (inBufferSize > sizeof (KLBoolean)) { + err = kl_check_error (klBufferTooLargeErr); + } else if (inBufferSize < sizeof (KLBoolean)) { + err = kl_check_error (klBufferTooSmallErr); + } + + if (!err && inOption == loginOption_RememberPrincipal) { + err = kim_preferences_set_remember_client_identity (prefs, *(KLBoolean *)inBuffer); + + } else if (!err && inOption == loginOption_RememberExtras) { + err = kim_preferences_set_remember_options (prefs, *(KLBoolean *)inBuffer); + } + + } else if (!err && (inOption == loginOption_MinimalTicketLifetime || + inOption == loginOption_MaximalTicketLifetime || + inOption == loginOption_MinimalRenewableLifetime || + inOption == loginOption_MaximalRenewableLifetime)) { + if (inBufferSize > sizeof (KLLifetime)) { + err = kl_check_error (klBufferTooLargeErr); + } else if (inBufferSize < sizeof (KLLifetime)) { + err = kl_check_error (klBufferTooSmallErr); + } + + if (!err && inOption == loginOption_MinimalTicketLifetime) { + err = kim_preferences_set_minimum_lifetime (prefs, *(KLLifetime *)inBuffer); + + } else if (!err && inOption == loginOption_MaximalTicketLifetime) { + err = kim_preferences_set_maximum_lifetime (prefs, *(KLLifetime *)inBuffer); + + } else if (!err && inOption == loginOption_MinimalRenewableLifetime) { + err = kim_preferences_set_minimum_renewal_lifetime (prefs, *(KLLifetime *)inBuffer); + + } else if (!err && inOption == loginOption_MaximalRenewableLifetime) { + err = kim_preferences_set_maximum_renewal_lifetime (prefs, *(KLLifetime *)inBuffer); + } + + } else if (!err && (inOption == loginOption_DefaultRenewableTicket || + inOption == loginOption_DefaultForwardableTicket || + inOption == loginOption_DefaultProxiableTicket || + inOption == loginOption_DefaultAddresslessTicket)) { + kim_options options = NULL; + + if (inBufferSize > sizeof (KLBoolean)) { + err = kl_check_error (klBufferTooLargeErr); + } else if (inBufferSize < sizeof (KLBoolean)) { + err = kl_check_error (klBufferTooSmallErr); + } + + if (!err) { + err = kim_preferences_get_options (prefs, &options); + } + + if (!err && inOption == loginOption_DefaultRenewableTicket) { + err = kim_options_set_renewable (options, *(KLBoolean *)inBuffer); + + } else if (!err && inOption == loginOption_DefaultForwardableTicket) { + err = kim_options_set_forwardable (options, *(KLBoolean *)inBuffer); + + } else if (!err && inOption == loginOption_DefaultProxiableTicket) { + err = kim_options_set_proxiable (options, *(KLBoolean *)inBuffer); + + } else if (!err && inOption == loginOption_DefaultAddresslessTicket) { + err = kim_options_set_addressless (options, *(KLBoolean *)inBuffer); + } + + if (!err) { + err = kim_preferences_set_options (prefs, options); + } + + kim_options_free (&options); + + } else if (!err && (inOption == loginOption_DefaultTicketLifetime || + inOption == loginOption_DefaultRenewableLifetime)) { + kim_options options = NULL; + + if (inBufferSize > sizeof (KLLifetime)) { + err = kl_check_error (klBufferTooLargeErr); + } else if (inBufferSize < sizeof (KLLifetime)) { + err = kl_check_error (klBufferTooSmallErr); + } + + if (!err) { + err = kim_preferences_get_options (prefs, &options); + } + + if (!err && inOption == loginOption_DefaultTicketLifetime) { + err = kim_options_set_lifetime (options, *(KLLifetime *)inBuffer); + + } else if (!err && inOption == loginOption_DefaultRenewableLifetime) { + err = kim_options_set_renewal_lifetime (options, *(KLLifetime *)inBuffer); + } + + if (!err) { + err = kim_preferences_set_options (prefs, options); + } + + kim_options_free (&options); + + } else { + err = kl_check_error (klInvalidOptionErr); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + } + + kim_preferences_free (&prefs); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +/* Realm configuration functions */ + +KLStatus KLFindKerberosRealmByName (const char *inRealmName, + KLIndex *outIndex) +{ + kim_error err = KIM_NO_ERROR; + char *realm = NULL; + + if (!err) { + err = KLGetKerberosDefaultRealmByName (&realm); + } + + if (!err) { + if (!strcmp (inRealmName, realm)) { + *outIndex = 0; + } else { + err = kl_check_error (klRealmDoesNotExistErr); + } + } + + kim_string_free ((kim_string *) &realm); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetKerberosRealm (KLIndex inIndex, + char **outRealmName) +{ + kim_error err = KIM_NO_ERROR; + + if (!outRealmName) { err = kl_check_error (klParameterErr); } + if (!err && inIndex != 0) { err = kl_check_error (klRealmDoesNotExistErr); } + + if (!err) { + err = KLGetKerberosDefaultRealmByName (outRealmName); + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetKerberosRealm (KLIndex inIndex, + const char *inRealmName) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLRemoveKerberosRealm (KLIndex inIndex) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLInsertKerberosRealm (KLIndex inInsertBeforeIndex, + const char *inRealmName) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLRemoveAllKerberosRealms (void) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLSize KLCountKerberosRealms (void) +{ + return 1; +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetKerberosDefaultRealm(KLIndex *outIndex) +{ + kim_error err = KIM_NO_ERROR; + + if (!outIndex) { err = kl_check_error (klParameterErr); } + + if (!err) { + *outIndex = 0; + } + + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetKerberosDefaultRealmByName (char **outRealmName) +{ + kim_error err = KIM_NO_ERROR; + krb5_context context = NULL; + char *realm = NULL; + + if (!outRealmName) { err = kl_check_error (klParameterErr); } + + if (!err) { + err = krb5_init_context (&context); + } + + if (!err) { + err = krb5_get_default_realm(context, &realm); + } + + if (!err) { + err = kim_string_copy ((kim_string *) outRealmName, realm); + } + + if (realm ) { krb5_free_default_realm (context, realm); } + if (context) { krb5_free_context (context); } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetKerberosDefaultRealm (KLIndex inIndex) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLSetKerberosDefaultRealmByName (const char *inRealm) +{ + return kl_check_error (klNoErr); +} + +/* ------------------------------------------------------------------------ */ + +/* KLPrincipal functions */ + +KLStatus KLCreatePrincipalFromTriplet (const char *inName, + const char *inInstance, + const char *inRealm, + KLPrincipal *outPrincipal) +{ + if (inInstance && strlen (inInstance) > 0) { + return kl_check_error (kim_identity_create_from_components (outPrincipal, + inRealm, + inName, + inInstance, + NULL)); + } else { + return kl_check_error (kim_identity_create_from_components (outPrincipal, + inRealm, + inName, + NULL)); + } +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLCreatePrincipalFromString (const char *inFullPrincipal, + KLKerberosVersion inKerberosVersion, + KLPrincipal *outPrincipal) +{ + return kl_check_error (kim_identity_create_from_string (outPrincipal, + inFullPrincipal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLCreatePrincipalFromKerberos5Principal (krb5_principal inKerberos5Principal, + KLPrincipal *outPrincipal) +{ + return kl_check_error (kim_identity_create_from_krb5_principal (outPrincipal, + NULL, /* context */ + inKerberos5Principal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLCreatePrincipalFromPrincipal (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal) +{ + return kl_check_error (kim_identity_copy (outPrincipal, inPrincipal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetTripletFromPrincipal (KLPrincipal inPrincipal, + char **outName, + char **outInstance, + char **outRealm) +{ + KLStatus err = klNoErr; + kim_string name = NULL; + kim_string instance = NULL; + kim_string realm = NULL; + kim_count count = 0; + + if (!inPrincipal) { return kl_check_error (klBadPrincipalErr); } + if (!outName ) { return kl_check_error (klParameterErr); } + if (!outInstance) { return kl_check_error (klParameterErr); } + if (!outRealm ) { return kl_check_error (klParameterErr); } + + if (!err) { + err = kim_identity_get_number_of_components (inPrincipal, &count); + if (!err && count > 2) { err = kl_check_error (klBadPrincipalErr); } + } + + if (!err) { + err = kim_identity_get_realm (inPrincipal, &realm); + } + + if (!err) { + err = kim_identity_get_component_at_index (inPrincipal, 0, &name); + } + + if (!err && count > 1) { + err = kim_identity_get_component_at_index (inPrincipal, 1, &instance); + } + + if (!err) { + *outName = (char *) name; + name = NULL; + *outInstance = (char *) instance; + instance = NULL; + *outRealm = (char *) realm; + realm = NULL; + } + + kim_string_free (&name); + kim_string_free (&instance); + kim_string_free (&realm); + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetStringFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outFullPrincipal) +{ + return kl_check_error (kim_identity_get_string (inPrincipal, + (kim_string *) outFullPrincipal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLGetDisplayStringFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outFullPrincipal) +{ + return kl_check_error (kim_identity_get_display_string (inPrincipal, + (kim_string *) outFullPrincipal)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLComparePrincipal (KLPrincipal inFirstPrincipal, + KLPrincipal inSecondPrincipal, + KLBoolean *outAreEquivalent) +{ + kim_error err = KIM_NO_ERROR; + kim_comparison comparison; + + err = kim_identity_compare (inFirstPrincipal, inSecondPrincipal, + &comparison); + + if (!err) { + *outAreEquivalent = kim_comparison_is_equal_to (comparison); + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLDisposePrincipal (KLPrincipal inPrincipal) +{ + kim_identity_free (&inPrincipal); + return klNoErr; +} + +/* ------------------------------------------------------------------------ */ + +/* KLLoginOptions functions */ + +KLStatus KLCreateLoginOptions (KLLoginOptions *outOptions) +{ + return kl_check_error (kim_options_create (outOptions)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetTicketLifetime (KLLoginOptions ioOptions, + KLLifetime inTicketLifetime) +{ + return kl_check_error (kim_options_set_lifetime (ioOptions, inTicketLifetime)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetForwardable (KLLoginOptions ioOptions, + KLBoolean inForwardable) +{ + return kl_check_error (kim_options_set_forwardable (ioOptions, inForwardable)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetProxiable (KLLoginOptions ioOptions, + KLBoolean inProxiable) +{ + return kl_check_error (kim_options_set_proxiable (ioOptions, inProxiable)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetRenewableLifetime (KLLoginOptions ioOptions, + KLLifetime inRenewableLifetime) +{ + KLStatus err = klNoErr; + + err = kim_options_set_renewable (ioOptions, inRenewableLifetime > 0); + + if (!err && inRenewableLifetime > 0) { + err = kim_options_set_renewal_lifetime (ioOptions, inRenewableLifetime); + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetAddressless (KLLoginOptions ioOptions, + KLBoolean inAddressless) +{ + return kl_check_error (kim_options_set_addressless (ioOptions, inAddressless)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetTicketStartTime (KLLoginOptions ioOptions, + KLTime inStartTime) +{ + return kl_check_error (kim_options_set_start_time (ioOptions, inStartTime)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLLoginOptionsSetServiceName (KLLoginOptions ioOptions, + const char *inServiceName) +{ + return kl_check_error (kim_options_set_service_name (ioOptions, inServiceName)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLDisposeLoginOptions(KLLoginOptions ioOptions) +{ + kim_options_free (&ioOptions); + return klNoErr; +} + +/* ------------------------------------------------------------------------ */ + +KLStatus KLDisposeString (char *inStringToDispose) +{ + kim_string_free ((kim_string *)&inStringToDispose); + return klNoErr; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLSetApplicationPrompter (KLPrompterProcPtr inPrompter) +{ + /* Deprecated */ + return klNoErr; +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLSetHomeDirectoryAccess (KLBoolean inAllowHomeDirectoryAccess) +{ + return kl_check_error (kim_library_set_allow_home_directory_access (inAllowHomeDirectoryAccess)); +} + +/* ------------------------------------------------------------------------ */ + +KLBoolean __KLAllowHomeDirectoryAccess (void) +{ + return kim_library_allow_home_directory_access (); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLSetAutomaticPrompting (KLBoolean inAllowAutomaticPrompting) +{ + return kl_check_error (kim_library_set_allow_automatic_prompting (inAllowAutomaticPrompting)); +} + +/* ------------------------------------------------------------------------ */ + +KLBoolean __KLAllowAutomaticPrompting (void) +{ + return kl_check_error (kim_library_allow_automatic_prompting ()); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLSetPromptMechanism (KLPromptMechanism inPromptMechanism) +{ + kim_error err = KIM_NO_ERROR; + + if (inPromptMechanism == klPromptMechanism_None) { + err = kim_library_set_allow_automatic_prompting (0); + } else { + err = kim_library_set_allow_automatic_prompting (1); + } + + return kl_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +KLPromptMechanism __KLPromptMechanism (void) +{ + kim_ui_environment environment = kim_library_ui_environment (); + + if (environment == KIM_UI_ENVIRONMENT_GUI) { + return klPromptMechanism_GUI; + } else if (environment == KIM_UI_ENVIRONMENT_CLI) { + return klPromptMechanism_CLI; + } + return klPromptMechanism_None; +} + +/* ------------------------------------------------------------------------ */ + +KLBoolean __KLAllowRememberPassword (void) +{ + return kl_check_error (kim_os_identity_allow_save_password ()); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLCreatePrincipalFromTriplet (const char *inName, + const char *inInstance, + const char *inRealm, + KLKerberosVersion inKerberosVersion, + KLPrincipal *outPrincipal) +{ + return kl_check_error (kim_identity_create_from_components (outPrincipal, + inRealm, + inName, + inInstance, + NULL)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLGetTripletFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outName, + char **outInstance, + char **outRealm) +{ + return KLGetTripletFromPrincipal (inPrincipal, + outName, outInstance, outRealm); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLCreatePrincipalFromKerberos5Principal (krb5_principal inPrincipal, + KLPrincipal *outPrincipal) +{ + return KLCreatePrincipalFromKerberos5Principal (inPrincipal, outPrincipal); + +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLGetKerberos5PrincipalFromPrincipal (KLPrincipal inPrincipal, + krb5_context inContext, + krb5_principal *outKrb5Principal) +{ + return kl_check_error (kim_identity_get_krb5_principal (inPrincipal, + inContext, + outKrb5Principal)); +} + +/* ------------------------------------------------------------------------ */ + +KLBoolean __KLPrincipalIsTicketGrantingService (KLPrincipal inPrincipal) +{ + kim_boolean is_tgt = FALSE; + kim_error err = kim_identity_is_tgt_service (inPrincipal, &is_tgt); + + return !err ? is_tgt : FALSE; +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLGetKeychainPasswordForPrincipal (KLPrincipal inPrincipal, + char **outPassword) +{ + return kl_check_error (kim_os_identity_get_saved_password (inPrincipal, + (kim_string *) outPassword)); +} + + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLPrincipalSetKeychainPassword (KLPrincipal inPrincipal, + const char *inPassword) +{ + return kl_check_error (kim_os_identity_set_saved_password (inPrincipal, + inPassword)); +} + +/* ------------------------------------------------------------------------ */ + +KLStatus __KLRemoveKeychainPasswordForPrincipal (KLPrincipal inPrincipal) +{ + return kl_check_error (kim_os_identity_remove_saved_password (inPrincipal)); +} + +#pragma mark - + +// --------------------------------------------------------------------------- + +krb5_get_init_creds_opt *__KLLoginOptionsGetKerberos5Options (KLLoginOptions ioOptions) +{ + return kim_options_init_cred_options (ioOptions); +} + +// --------------------------------------------------------------------------- + +KLTime __KLLoginOptionsGetStartTime (KLLoginOptions ioOptions) +{ + return kim_options_start_time (ioOptions); +} + +// --------------------------------------------------------------------------- + +char *__KLLoginOptionsGetServiceName (KLLoginOptions ioOptions) +{ + return kim_options_service_name (ioOptions); +} + + + +#endif /* KIM_TO_KLL_SHIM */ diff --git a/krb5-1-7/src/kim/lib/mac/KerberosLogin.exports b/krb5-1-7/src/kim/lib/mac/KerberosLogin.exports new file mode 100644 index 000000000..9fd85f41f --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/KerberosLogin.exports @@ -0,0 +1,107 @@ + +# Public API: + +KLAcquireTickets +KLAcquireNewTickets +KLAcquireTicketsWithPassword +KLAcquireNewTicketsWithPassword + +KLAcquireInitialTickets +KLAcquireNewInitialTickets +KLAcquireInitialTicketsWithPassword +KLAcquireNewInitialTicketsWithPassword +KLAcquireNewInitialTicketCredentialsWithPassword +KLStoreNewInitialTicketCredentials + +KLVerifyInitialTickets +KLVerifyInitialTicketCredentials +KLAcquireNewInitialTicketsWithKeytab + +KLChangePassword +KLChangePasswordWithPasswords +KLRenewInitialTickets +KLValidateInitialTickets +KLDestroyTickets + +KLLastChangedTime +KLCacheHasValidTickets +KLTicketStartTime +KLTicketExpirationTime +KLSetSystemDefaultCache + +KLHandleError +KLGetErrorString + +KLCancelAllDialogs + +KLSetApplicationOptions +KLGetApplicationOptions + +KLSetIdleCallback +KLGetIdleCallback + +KLGetDefaultLoginOption +KLSetDefaultLoginOption + +KLFindKerberosRealmByName +KLGetKerberosRealm +KLSetKerberosRealm +KLRemoveKerberosRealm +KLInsertKerberosRealm +KLRemoveAllKerberosRealms +KLCountKerberosRealms +KLGetKerberosDefaultRealm +KLGetKerberosDefaultRealmByName +KLSetKerberosDefaultRealm +KLSetKerberosDefaultRealmByName + +KLCreatePrincipalFromTriplet +KLCreatePrincipalFromString +KLGetTripletFromPrincipal +KLGetStringFromPrincipal +KLGetDisplayStringFromPrincipal +KLComparePrincipal +KLDisposePrincipal + +KLCreateLoginOptions +KLLoginOptionsSetTicketLifetime +KLLoginOptionsSetForwardable +KLLoginOptionsSetProxiable +KLLoginOptionsSetRenewableLifetime +KLLoginOptionsSetAddressless +KLLoginOptionsSetTicketStartTime +KLLoginOptionsSetServiceName +KLDisposeLoginOptions + +KLDisposeString + +# Private APIs being used by external callers: + +#__KLChangePasswordWithPasswordsCompat +#__KLAcquireInitialTicketsForCache +#__KLPrompter + +__KLSetApplicationPrompter + +__KLSetHomeDirectoryAccess +__KLAllowHomeDirectoryAccess + +__KLSetAutomaticPrompting +__KLAllowAutomaticPrompting +__KLSetPromptMechanism +__KLPromptMechanism +__KLAllowRememberPassword + +__KLCreatePrincipalFromTriplet +__KLGetTripletFromPrincipal +__KLCreatePrincipalFromKerberos5Principal +__KLGetKerberos5PrincipalFromPrincipal +__KLPrincipalIsTicketGrantingService + +__KLGetKeychainPasswordForPrincipal +__KLPrincipalSetKeychainPassword +__KLRemoveKeychainPasswordForPrincipal + +__KLLoginOptionsGetKerberos5Options +__KLLoginOptionsGetStartTime +__KLLoginOptionsGetServiceName diff --git a/krb5-1-7/src/kim/lib/mac/KerberosLogin.h b/krb5-1-7/src/kim/lib/mac/KerberosLogin.h new file mode 100644 index 000000000..8dc49e18d --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/KerberosLogin.h @@ -0,0 +1,456 @@ +/* +* Copyright 2008 Massachusetts Institute of Technology. +* All Rights Reserved. +* +* Export of this software from the United States of America may +* require a specific license from the United States Government. +* It is the responsibility of any person or organization contemplating +* export to obtain such a license before exporting. +* +* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +* distribute this software and its documentation for any purpose and +* without fee is hereby granted, provided that the above copyright +* notice appear in all copies and that both that copyright notice and +* this permission notice appear in supporting documentation, and that +* the name of M.I.T. not be used in advertising or publicity pertaining +* to distribution of the software without specific, written prior +* permission. Furthermore if you modify this software you must label +* your software as modified software and not distribute it in such a +* fashion that it might be confused with the original M.I.T. software. +* M.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 __KERBEROSLOGIN__ +#define __KERBEROSLOGIN__ + +#include + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 30203 +# define KERBEROSLOGIN_DEPRECATED __attribute__((deprecated)) +#else +# define KERBEROSLOGIN_DEPRECATED +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if TARGET_OS_MAC +# pragma pack(push,2) +#endif + +/* + * Kerberos version constants + */ +enum { + kerberosVersion_Any = 0, + kerberosVersion_V4 = 1, + kerberosVersion_V5 = 2, + kerberosVersion_All = 0xFFFFFFFF +}; +typedef int32_t KLEKerberosVersion; + +/* + * Dialog identifier constants + */ +enum { + loginLibrary_LoginDialog, + loginLibrary_OptionsDialog, + loginLibrary_ChangePasswordDialog, + loginLibrary_ProgressDialog, + loginLibrary_PrompterDialog, + loginLibrary_UnknownDialog = -1 +}; +typedef int32_t KLEDialogIdentifiers; + + +/* + * Option identifier constants + */ +enum { + /* Initial values and ranges */ + loginOption_LoginName = 'name', + loginOption_LoginInstance = 'inst', + + loginOption_RememberPrincipal = 'prin', + loginOption_RememberExtras = 'extr', + + loginOption_MinimalTicketLifetime = '-lif', + loginOption_MaximalTicketLifetime = '+lif', + loginOption_DefaultTicketLifetime = '0lif', + + loginOption_DefaultRenewableTicket = '0rtx', + loginOption_MinimalRenewableLifetime = '-rlf', + loginOption_MaximalRenewableLifetime = '+rlf', + loginOption_DefaultRenewableLifetime = '0rlf', + + loginOption_DefaultForwardableTicket = '0fwd', + loginOption_DefaultProxiableTicket = '0prx', + loginOption_DefaultAddresslessTicket = '0adr' +}; +typedef int32_t KLEDefaultLoginOptions; + + +/* + * Realm list constants + */ +enum { + realmList_Start = 0, + realmList_End = 0xFFFF +}; +typedef int32_t KLERealmListIndexes; + +#define klFirstError 19276 +#define klLastError 19876 + +/* + * Error codes + */ +enum { + klNoErr = 0, + + /* Parameter errors */ + klParameterErr = 19276, + klBadPrincipalErr, + klBadPasswordErr, + klBadLoginOptionsErr, + klInvalidVersionErr, + klCapsLockErr, + klBadV5ContextErr, + + /* Get/SetKerberosOption errors */ + klBufferTooSmallErr = 19376, + klBufferTooLargeErr, + klInvalidOptionErr, + klBadOptionValueErr, + + /* Runtime Login errors */ + klUserCanceledErr = 19476, + klMemFullErr, + klPreferencesReadErr, + klPreferencesWriteErr, + klV5InitializationFailedErr, + klPrincipalDoesNotExistErr, + klSystemDefaultDoesNotExistErr, + klCredentialsExpiredErr, + klNoRealmsErr, + klRealmDoesNotExistErr, + klNoCredentialsErr, + klCredentialsBadAddressErr, + klCacheDoesNotExistErr, + klNoHostnameErr, + klCredentialsNeedValidationErr, + + /* Password changing errors */ + klPasswordMismatchErr = 19576, + klInsecurePasswordErr, + klPasswordChangeFailedErr, + + /* Login IPC errors */ + klCantContactServerErr = 19776, + klCantDisplayUIErr, + klServerInsecureErr + +}; +typedef int32_t KLEStatus; + +/* + * Types + */ + +typedef int32_t KLStatus; /* one of KLEStatus */ +typedef u_int32_t KLKerberosVersion; /* one of KLEKerberosVersion */ +typedef u_int32_t KLDefaultLoginOption; /* one of KLEDefaultLoginOptions */ +typedef u_int32_t KLLoginMode; /* one of KLELoginMode */ +typedef u_int32_t KLDialogIdentifier; /* one of KLEDialogIdentifiers */ +typedef u_int32_t KLIndex; /* index (used for the realm list) */ +typedef u_int32_t KLLifetime; /* Lifetime in seconds */ +typedef u_int32_t KLTime; /* Unix time (seconds since 1/1/1970 00:00:00 GMT) */ +typedef u_int32_t KLSize; /* size of a buffer */ +typedef u_int32_t KLRefCon; /* application ref con */ +typedef int8_t KLBoolean; /* true or false! (unsigned 8 byte value to match Boolean) */ +typedef int16_t KLSInt16; /* used for Darwin-compat for KLApplicationOptions */ + +/* Callback API for Kerberos Login Mach IPC idle filter */ +typedef void (*KLIdleCallback) (KLRefCon appData); +#define CallKLIdleCallback(userRoutine, appData) ((userRoutine) (appData)) + +/* Principal information */ +typedef kim_identity KLPrincipal; + +/* Login Options */ +typedef kim_options KLLoginOptions; + +/* + * + * Functions + * + */ + +/* Deprecated functions -- provided for compatibility with KfM 4.0 */ + +KLStatus KLAcquireTickets (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal, + char **outCredCacheName) + KERBEROSLOGIN_DEPRECATED; + +KLStatus KLAcquireNewTickets (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal, + char **outCredCacheName) + KERBEROSLOGIN_DEPRECATED; + +KLStatus KLAcquireTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) + KERBEROSLOGIN_DEPRECATED; + +KLStatus KLAcquireNewTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName) + KERBEROSLOGIN_DEPRECATED; + +KLStatus KLSetApplicationOptions (const void *inAppOptions) + KERBEROSLOGIN_DEPRECATED; + +KLStatus KLGetApplicationOptions (void *outAppOptions) + KERBEROSLOGIN_DEPRECATED; + + +/* Kerberos Login high-level API */ +KLStatus KLAcquireInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName); + +KLStatus KLAcquireNewInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName); + +KLStatus KLDestroyTickets (KLPrincipal inPrincipal); + +KLStatus KLChangePassword (KLPrincipal inPrincipal); + + +/* Kerberos Login dialog low level functions */ + +KLStatus KLAcquireInitialTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName); + +KLStatus KLAcquireNewInitialTicketsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + char **outCredCacheName); + +KLStatus KLAcquireNewInitialTicketCredentialsWithPassword (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inPassword, + krb5_context inV5Context, + KLBoolean *outGotV4Credentials, + KLBoolean *outGotV5Credentials, + void *outV4Credentials, + krb5_creds *outV5Credentials); + +KLStatus KLStoreNewInitialTicketCredentials (KLPrincipal inPrincipal, + krb5_context inV5Context, + void *inV4Credentials, + krb5_creds *inV5Credentials, + char **outCredCacheName); + +KLStatus KLVerifyInitialTickets (KLPrincipal inPrincipal, + KLBoolean inFailIfNoHostKey, + char **outCredCacheName); + +KLStatus KLVerifyInitialTicketCredentials (void *inV4Credentials, + krb5_creds *inV5Credentials, + KLBoolean inFailIfNoHostKey); + +KLStatus KLAcquireNewInitialTicketsWithKeytab (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + const char *inKeytabName, + char **outCredCacheName); + +KLStatus KLRenewInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + KLPrincipal *outPrincipal, + char **outCredCacheName); + +KLStatus KLValidateInitialTickets (KLPrincipal inPrincipal, + KLLoginOptions inLoginOptions, + char **outCredCacheName); + +KLStatus KLLastChangedTime (KLTime *outLastChangedTime); + +KLStatus KLCacheHasValidTickets (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLBoolean *outFoundValidTickets, + KLPrincipal *outPrincipal, + char **outCredCacheName); + +KLStatus KLTicketStartTime (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLTime *outStartTime); + +KLStatus KLTicketExpirationTime (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + KLTime *outExpirationTime); + +KLStatus KLSetSystemDefaultCache (KLPrincipal inPrincipal); + +KLStatus KLHandleError (KLStatus inError, + KLDialogIdentifier inDialogIdentifier, + KLBoolean inShowAlert); + +KLStatus KLGetErrorString (KLStatus inError, + char **outErrorString); + +KLStatus KLCancelAllDialogs (void); + +/* Kerberos change password dialog low level functions */ + +KLStatus KLChangePasswordWithPasswords (KLPrincipal inPrincipal, + const char *inOldPassword, + const char *inNewPassword, + KLBoolean *outRejected, + char **outRejectionError, + char **outRejectionDescription); + +/* Application Configuration functions */ + +KLStatus KLSetIdleCallback (const KLIdleCallback inCallback, + const KLRefCon inRefCon); + +KLStatus KLGetIdleCallback (KLIdleCallback* inCallback, + KLRefCon* inRefCon); + +/* Library configuration functions */ + +KLStatus KLGetDefaultLoginOption (const KLDefaultLoginOption inOption, + void *ioBuffer, + KLSize *ioBufferSize); + +KLStatus KLSetDefaultLoginOption (const KLDefaultLoginOption inOption, + const void *inBuffer, + const KLSize inBufferSize); + +/* Realm configuration functions */ + +KLStatus KLFindKerberosRealmByName (const char *inRealmName, + KLIndex *outIndex); + +KLStatus KLGetKerberosRealm (KLIndex inIndex, + char **outRealmName); + +KLStatus KLSetKerberosRealm (KLIndex inIndex, + const char *inRealmName); + +KLStatus KLRemoveKerberosRealm (KLIndex inIndex); + +KLStatus KLInsertKerberosRealm (KLIndex inInsertBeforeIndex, + const char *inRealmName); + +KLStatus KLRemoveAllKerberosRealms (void); + +KLSize KLCountKerberosRealms (void); + +KLStatus KLGetKerberosDefaultRealm(KLIndex *outIndex); + +KLStatus KLGetKerberosDefaultRealmByName (char **outRealmName); + +KLStatus KLSetKerberosDefaultRealm (KLIndex inIndex); + +KLStatus KLSetKerberosDefaultRealmByName (const char *inRealm); + +/* KLPrincipal functions */ + +KLStatus KLCreatePrincipalFromTriplet (const char *inName, + const char *inInstance, + const char *inRealm, + KLPrincipal *outPrincipal); + +KLStatus KLCreatePrincipalFromString (const char *inFullPrincipal, + KLKerberosVersion inKerberosVersion, + KLPrincipal *outPrincipal); + +KLStatus KLCreatePrincipalFromKerberos5Principal (krb5_principal inKerberos5Principal, + KLPrincipal *outPrincipal); + +KLStatus KLCreatePrincipalFromPrincipal (KLPrincipal inPrincipal, + KLPrincipal *outPrincipal); + +KLStatus KLGetTripletFromPrincipal (KLPrincipal inPrincipal, + char **outName, + char **outInstance, + char **outRealm); + +KLStatus KLGetStringFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outFullPrincipal); + +KLStatus KLGetDisplayStringFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outFullPrincipal); + +KLStatus KLComparePrincipal (KLPrincipal inFirstPrincipal, + KLPrincipal inSecondPrincipal, + KLBoolean *outAreEquivalent); + +KLStatus KLDisposePrincipal (KLPrincipal inPrincipal); + +/* KLLoginOptions functions */ + +KLStatus KLCreateLoginOptions (KLLoginOptions *outOptions); + +KLStatus KLLoginOptionsSetTicketLifetime (KLLoginOptions ioOptions, + KLLifetime inTicketLifetime); + +KLStatus KLLoginOptionsSetForwardable (KLLoginOptions ioOptions, + KLBoolean inForwardable); + +KLStatus KLLoginOptionsSetProxiable (KLLoginOptions ioOptions, + KLBoolean inProxiable); + +KLStatus KLLoginOptionsSetRenewableLifetime (KLLoginOptions ioOptions, + KLLifetime inRenewableLifetime); + +KLStatus KLLoginOptionsSetAddressless (KLLoginOptions ioOptions, + KLBoolean inAddressless); + +KLStatus KLLoginOptionsSetTicketStartTime (KLLoginOptions ioOptions, + KLTime inStartTime); + +KLStatus KLLoginOptionsSetServiceName (KLLoginOptions ioOptions, + const char *inServiceName); + +KLStatus KLDisposeLoginOptions(KLLoginOptions ioOptions); + + +/* Misc function */ + +KLStatus KLDisposeString (char *inStringToDispose); + +#if TARGET_OS_MAC +# pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __KERBEROSLOGIN__ */ diff --git a/krb5-1-7/src/kim/lib/mac/KerberosLoginErrors.et b/krb5-1-7/src/kim/lib/mac/KerberosLoginErrors.et new file mode 100755 index 000000000..22ee35274 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/KerberosLoginErrors.et @@ -0,0 +1,88 @@ +# $Copyright: +# +# Copyrigh 1998-2008 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 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, +# OpenVision, Oracle, Sun Soft, 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). +# $ + +# $Header$ + +error_table_base 19276 +error_table_manager "Kerberos Login" +error_table KLL + +# 19276 +error_code klParameterErr, "Invalid argument" +error_code klBadPrincipalErr, "Invalid principal" +error_code klBadPasswordErr, "Invalid password argument" +error_code klBadLoginOptionsErr, "Invalid login options argument" +error_code klInvalidVersionErr, "Invalid Kerberos version (not 4 or 5)" +error_code klCapsLockErr, "Password Incorrect (check your Caps Lock)" +error_code klBadV5ContextErr, "Invalid Kerberos 5 context" + +# 19376 +index 100 +error_code klBufferTooSmallErr, "Kerberos default login option buffer too small" +error_code klBufferTooLargeErr, "Kerberos default login option buffer too large" +error_code klInvalidOptionErr, "Invalid Kerberos default login option" +error_code klBadOptionValueErr, "Invalid value for Kerberos default login option" + +# 19476 +index 200 +error_code klUserCanceledErr, "The user cancelled the operation" +error_code klMemFullErr, "Out of memory" +error_code klPreferencesReadErr, "Unable to read Kerberos Login preferences. The file may be missing, inaccessible or corrupted." +error_code klPreferencesWriteErr, "Unable to write Kerberos Login preferences. The file may be inaccessible." +error_code klV5InitializationFailedErr, "Unable to initialize Kerberos v5" +error_code klPrincipalDoesNotExistErr, "Principal does not exist" +error_code klSystemDefaultDoesNotExistErr, "The system default cache does not exist yet" +error_code klCredentialsExpiredErr, "Your tickets have expired" +error_code klNoRealmsErr, "There are no realms" +error_code klRealmDoesNotExistErr, "The specified realm is not in your configuration file or does not exist" +error_code klNoCredentialsErr, "You do not have tickets for this principal and Kerberos version" +error_code klCredentialsBadAddressErr, "The IP address(es) in your tickets do not match your computer's IP address" +error_code klCacheDoesNotExistErr, "The specified cache does not exist" +error_code klNoHostnameErr, "Unable to get local hostname or address information" +error_code klCredentialsNeedValidationErr, "Your tickets need to be validated." +# 19576 +index 300 +error_code klPasswordMismatchErr, "Password mismatch" +error_code klInsecurePasswordErr, "Your new password is insecure; please pick another one" +error_code klPasswordChangeFailedErr, "Kerberos password change failed." +# 19776 +index 500 +error_code klCantContactServerErr, "Can't find KerberosLoginServer" +error_code klCantDisplayUIErr, "Can't display user interface from this environment" +error_code klServerInsecureErr, "Fatal security error. Client/server effective uid mismatch!" + +end diff --git a/krb5-1-7/src/kim/lib/mac/KerberosLoginPrivate.h b/krb5-1-7/src/kim/lib/mac/KerberosLoginPrivate.h new file mode 100644 index 000000000..52e10fcd1 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/KerberosLoginPrivate.h @@ -0,0 +1,123 @@ +/* +* Copyright 1998-2008 Massachusetts Institute of Technology. +* All Rights Reserved. +* +* Export of this software from the United States of America may +* require a specific license from the United States Government. +* It is the responsibility of any person or organization contemplating +* export to obtain such a license before exporting. +* +* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +* distribute this software and its documentation for any purpose and +* without fee is hereby granted, provided that the above copyright +* notice appear in all copies and that both that copyright notice and +* this permission notice appear in supporting documentation, and that +* the name of M.I.T. not be used in advertising or publicity pertaining +* to distribution of the software without specific, written prior +* permission. Furthermore if you modify this software you must label +* your software as modified software and not distribute it in such a +* fashion that it might be confused with the original M.I.T. software. +* M.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 __KERBEROSLOGINPRIVATE__ +#define __KERBEROSLOGINPRIVATE__ + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + klPromptMechanism_Autodetect = 0, + klPromptMechanism_GUI = 1, + klPromptMechanism_CLI = 2, + klPromptMechanism_None = 0xFFFFFFFF +}; +typedef uint32_t KLPromptMechanism; + +/*************/ +/*** Types ***/ +/*************/ + +#ifdef KERBEROSLOGIN_DEPRECATED + +typedef krb5_error_code (*KLPrompterProcPtr) (krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]); +KLStatus __KLSetApplicationPrompter (KLPrompterProcPtr inPrompter); + +#endif /* KERBEROSLOGIN_DEPRECATED */ + +/*****************/ +/*** Functions ***/ +/*****************/ + +KLStatus __KLSetHomeDirectoryAccess (KLBoolean inAllowHomeDirectoryAccess); +KLBoolean __KLAllowHomeDirectoryAccess (void); + +KLStatus __KLSetAutomaticPrompting (KLBoolean inAllowAutomaticPrompting); +KLBoolean __KLAllowAutomaticPrompting (void); + +KLBoolean __KLAllowRememberPassword (void); + +KLStatus __KLSetPromptMechanism (KLPromptMechanism inPromptMechanism); +KLPromptMechanism __KLPromptMechanism (void); + +KLStatus __KLCreatePrincipalFromTriplet (const char *inName, + const char *inInstance, + const char *inRealm, + KLKerberosVersion inKerberosVersion, + KLPrincipal *outPrincipal); + +KLStatus __KLGetTripletFromPrincipal (KLPrincipal inPrincipal, + KLKerberosVersion inKerberosVersion, + char **outName, + char **outInstance, + char **outRealm); + +KLStatus __KLCreatePrincipalFromKerberos5Principal (krb5_principal inPrincipal, + KLPrincipal *outPrincipal); + +KLStatus __KLGetKerberos5PrincipalFromPrincipal (KLPrincipal inPrincipal, + krb5_context inContext, + krb5_principal *outKrb5Principal); + +KLStatus __KLGetRealmFromPrincipal (KLPrincipal inPrincipal, char **outRealm); + +KLBoolean __KLPrincipalIsTicketGrantingService (KLPrincipal inPrincipal); + +KLStatus __KLGetKeychainPasswordForPrincipal (KLPrincipal inPrincipal, + char **outPassword); + +KLStatus __KLPrincipalSetKeychainPassword (KLPrincipal inPrincipal, + const char *inPassword); + +KLStatus __KLRemoveKeychainPasswordForPrincipal (KLPrincipal inPrincipal); + +#if TARGET_OS_MAC +# if defined(__MWERKS__) +# pragma import reset +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __KERBEROSLOGINPRIVATE__ */ + diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_debug.c b/krb5-1-7/src/kim/lib/mac/kim_os_debug.c new file mode 100644 index 000000000..e4236872f --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_debug.c @@ -0,0 +1,37 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "kim_os_private.h" + +/* ------------------------------------------------------------------------ */ + +void kim_os_debug_print (kim_string in_string) +{ + dprintf (in_string); +} diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_identity.c b/krb5-1-7/src/kim/lib/mac/kim_os_identity.c new file mode 100644 index 000000000..a9c92d73a --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_identity.c @@ -0,0 +1,314 @@ +/* + * $Header$ + * + * 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. + */ + +#include +#include +#include + +#include "kim_os_private.h" + +/* ------------------------------------------------------------------------ */ + +kim_boolean kim_os_identity_allow_save_password (void) +{ + kim_boolean disabled = 0; + CFPropertyListRef disable_pref = NULL; + + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + KIM_PREFERENCES_FILE, + kCFPreferencesAnyUser, + kCFPreferencesAnyHost); + if (!disable_pref) { + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + KIM_PREFERENCES_FILE, + kCFPreferencesAnyUser, + kCFPreferencesCurrentHost); + } + + if (!disable_pref) { + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + KA_PREFERENCES_FILE, + kCFPreferencesAnyUser, + kCFPreferencesAnyHost); + } + + if (!disable_pref) { + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + KA_PREFERENCES_FILE, + kCFPreferencesAnyUser, + kCFPreferencesCurrentHost); + } + + disabled = (disable_pref && + CFGetTypeID (disable_pref) == CFBooleanGetTypeID () && + CFBooleanGetValue (disable_pref)); + + if (disable_pref) { CFRelease (disable_pref); } + + return !disabled; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_identity_get_saved_password (kim_identity in_identity, + kim_string *out_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string realm = NULL; + kim_string name = NULL; + void *buffer = NULL; + UInt32 length = 0; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !kim_library_allow_home_directory_access ()) { + err = check_error (ENOENT); /* simulate no password found */ + } + + if (!err && !kim_os_identity_allow_save_password ()) { + err = kim_os_identity_remove_saved_password (in_identity); + if (!err) { + err = check_error (ENOENT); /* simulate no password found */ + } + } + + if (!err) { + err = kim_identity_get_components_string (in_identity, &name); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + err = SecKeychainFindGenericPassword (nil, + strlen (realm), realm, + strlen (name), name, + &length, &buffer, + nil); + + if (!err && !buffer) { err = check_error (ENOENT); } + } + + if (!err) { + err = kim_string_create_from_buffer (out_password, buffer, length); + } + + kim_string_free (&name); + kim_string_free (&realm); + if (buffer) { SecKeychainItemFreeContent (NULL, buffer); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_identity_set_saved_password (kim_identity in_identity, + kim_string in_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string realm = NULL; + kim_string name = NULL; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !kim_library_allow_home_directory_access ()) { + return KIM_NO_ERROR; /* simulate no error */ + } + + if (!err && !kim_os_identity_allow_save_password ()) { + return kim_os_identity_remove_saved_password (in_identity); + } + + if (!err) { + err = kim_identity_get_components_string (in_identity, &name); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + SecKeychainItemRef itemRef = NULL; + UInt32 namelen = strlen (name); + UInt32 realmlen = strlen (realm); + + /* Add the password to the keychain */ + err = SecKeychainAddGenericPassword (nil, + realmlen, realm, + namelen, name, + strlen (in_password), in_password, + &itemRef); + + if (err == errSecDuplicateItem) { + /* We've already stored a password for this principal + * but it might have changed so update it */ + void *buffer = NULL; + UInt32 length = 0; + + err = SecKeychainFindGenericPassword (nil, + realmlen, realm, + namelen, name, + &length, &buffer, + &itemRef); + + if (!err) { + SecKeychainAttribute attrs[] = { + { kSecAccountItemAttr, namelen, (char *) name }, + { kSecServiceItemAttr, realmlen, (char *) realm } }; + UInt32 count = sizeof(attrs) / sizeof(attrs[0]); + const SecKeychainAttributeList attrList = { count, attrs }; + + err = SecKeychainItemModifyAttributesAndData (itemRef, + &attrList, + strlen (in_password), + in_password); + } + + } else if (!err) { + /* We added a new entry, add a descriptive label */ + SecKeychainAttributeList *copiedAttrs = NULL; + SecKeychainAttributeInfo attrInfo; + UInt32 tag = 7; + UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING; + kim_string label = NULL; + + attrInfo.count = 1; + attrInfo.tag = &tag; + attrInfo.format = &format; + + err = SecKeychainItemCopyAttributesAndData (itemRef, &attrInfo, + NULL, &copiedAttrs, + 0, NULL); + + if (!err) { + /* Label format used by Apple patches */ + err = kim_string_create_from_format (&label, "%s (%s)", + realm, name); + } + + if (!err) { + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + + /* Copy the tag they gave us and copy in our label */ + attr.tag = copiedAttrs->attr->tag; + attr.length = strlen (label); + attr.data = (char *) label; + + attrList.count = 1; + attrList.attr = &attr; + + /* And modify. */ + err = SecKeychainItemModifyAttributesAndData (itemRef, &attrList, + 0, NULL); + } + + if (label ) { kim_string_free (&label); } + if (copiedAttrs) { SecKeychainItemFreeAttributesAndData (copiedAttrs, NULL); } + } + + if (itemRef) { CFRelease (itemRef); } + } + + kim_string_free (&name); + kim_string_free (&realm); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_identity_remove_saved_password (kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_string realm = NULL; + kim_string name = NULL; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && !kim_library_allow_home_directory_access ()) { + return KIM_NO_ERROR; /* simulate no error */ + } + + if (!err) { + err = kim_identity_get_components_string (in_identity, &name); + } + + if (!err) { + err = kim_identity_get_realm (in_identity, &realm); + } + + if (!err) { + SecKeychainItemRef itemRef = NULL; + UInt32 namelen = strlen (name); + UInt32 realmlen = strlen (realm); + void *buffer = NULL; + UInt32 length = 0; + + err = SecKeychainFindGenericPassword (nil, + realmlen, realm, + namelen, name, + &length, &buffer, + &itemRef); + + if (!err) { + err = SecKeychainItemDelete (itemRef); + + } else if (err == errSecItemNotFound) { + err = KIM_NO_ERROR; /* No password not an error */ + } + + if (itemRef) { CFRelease (itemRef); } + } + + kim_string_free (&name); + kim_string_free (&realm); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_identity_create_for_username (kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + struct passwd *pw = getpwuid (getuid ()); + if (pw) { + err = kim_identity_create_from_string (out_identity, pw->pw_name); + } else { + *out_identity = KIM_IDENTITY_ANY; + } + } + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_library.c b/krb5-1-7/src/kim/lib/mac/kim_os_library.c new file mode 100644 index 000000000..f3b269084 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_library.c @@ -0,0 +1,332 @@ +/* + * $Header$ + * + * 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. + */ + +#include +#include +#include +#include "k5-int.h" +#include "k5-thread.h" +#include + +#include "kim_os_private.h" + + +static k5_mutex_t g_bundle_lookup_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +MAKE_INIT_FUNCTION(kim_os_library_thread_init); +MAKE_FINI_FUNCTION(kim_os_library_thread_fini); + +/* ------------------------------------------------------------------------ */ + +static int kim_os_library_thread_init (void) +{ + kim_error err = KIM_NO_ERROR; + + if (!err) { + err = k5_mutex_finish_init (&g_bundle_lookup_mutex); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void kim_os_library_thread_fini (void) +{ + if (!INITIALIZER_RAN (kim_os_library_thread_init) || PROGRAM_EXITING ()) { + return; + } + k5_mutex_destroy (&g_bundle_lookup_mutex); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_library_lock_for_bundle_lookup (void) +{ + kim_error err = CALL_INIT_FUNCTION (kim_os_library_thread_init); + + if (!err) { + err = k5_mutex_lock (&g_bundle_lookup_mutex); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_library_unlock_for_bundle_lookup (void) +{ + kim_error err = CALL_INIT_FUNCTION (kim_os_library_thread_init); + + if (!err) { + err = k5_mutex_unlock (&g_bundle_lookup_mutex); + } + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_boolean kim_os_library_caller_uses_gui (void) +{ + kim_boolean caller_uses_gui = 0; + + /* Check for the HIToolbox (Carbon) or AppKit (Cocoa). + * If either is loaded, we are a GUI app! */ + CFBundleRef appKitBundle = CFBundleGetBundleWithIdentifier (CFSTR ("com.apple.AppKit")); + CFBundleRef hiToolBoxBundle = CFBundleGetBundleWithIdentifier (CFSTR ("com.apple.HIToolbox")); + + if (hiToolBoxBundle && CFBundleIsExecutableLoaded (hiToolBoxBundle)) { + caller_uses_gui = 1; /* Using Carbon */ + } + + if (appKitBundle && CFBundleIsExecutableLoaded (appKitBundle)) { + caller_uses_gui = 1; /* Using Cocoa */ + } + + return caller_uses_gui; +} + +/* ------------------------------------------------------------------------ */ + +kim_ui_environment kim_os_library_get_ui_environment (void) +{ +#ifdef KIM_BUILTIN_UI + kim_boolean has_gui_access = 0; + SessionAttributeBits sattrs = 0L; + + has_gui_access = ((SessionGetInfo (callerSecuritySession, + NULL, &sattrs) == noErr) && + (sattrs & sessionHasGraphicAccess)); + + if (has_gui_access && kim_os_library_caller_uses_gui ()) { + return KIM_UI_ENVIRONMENT_GUI; + } + + { + int fd_stdin = fileno (stdin); + int fd_stdout = fileno (stdout); + char *fd_stdin_name = ttyname (fd_stdin); + + /* Session info isn't reliable for remote sessions. + * Check manually for terminal access with file descriptors */ + if (isatty (fd_stdin) && isatty (fd_stdout) && fd_stdin_name) { + return KIM_UI_ENVIRONMENT_CLI; + } + } + + /* If we don't have a CLI but can talk to the GUI, use that */ + if (has_gui_access) { + return KIM_UI_ENVIRONMENT_GUI; + } + + kim_debug_printf ("kim_os_library_get_ui_environment(): no way to talk to the user."); +#endif + return KIM_UI_ENVIRONMENT_NONE; +} + +/* ------------------------------------------------------------------------ */ + +kim_boolean kim_os_library_caller_is_server (void) +{ + CFBundleRef mainBundle = CFBundleGetMainBundle (); + if (mainBundle) { + CFStringRef mainBundleID = CFBundleGetIdentifier (mainBundle); + if (mainBundleID) { + CFComparisonResult result; + result = CFStringCompare (mainBundleID, CFSTR(kim_os_agent_bundle_id), 0); + if (result == kCFCompareEqualTo) { + return TRUE; + } + } + } + + return FALSE; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_library_get_application_path (kim_string *out_path) +{ + kim_error err = KIM_NO_ERROR; + kim_string path = NULL; + CFBundleRef bundle = CFBundleGetMainBundle (); + + if (!err && !out_path) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + /* Check if the caller is a bundle */ + if (!err && bundle) { + CFURLRef bundle_url = CFBundleCopyBundleURL (bundle); + CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL (bundle); + CFURLRef executable_url = CFBundleCopyExecutableURL (bundle); + CFURLRef absolute_url = NULL; + CFStringRef cfpath = NULL; + + if (bundle_url && resources_url && !CFEqual (bundle_url, resources_url)) { + absolute_url = CFURLCopyAbsoluteURL (bundle_url); + } else if (executable_url) { + absolute_url = CFURLCopyAbsoluteURL (executable_url); + } + + if (absolute_url) { + cfpath = CFURLCopyFileSystemPath (absolute_url, + kCFURLPOSIXPathStyle); + if (!cfpath) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + } + + if (!err && cfpath) { + err = kim_os_string_create_from_cfstring (&path, cfpath); + } + + if (cfpath ) { CFRelease (cfpath); } + if (absolute_url ) { CFRelease (absolute_url); } + if (bundle_url ) { CFRelease (bundle_url); } + if (resources_url ) { CFRelease (resources_url); } + if (executable_url) { CFRelease (executable_url); } + } + + /* Caller is not a bundle, try _NSGetExecutablePath */ + /* Note: this does not work on CFM applications */ + if (!err && !path) { + char *buffer = NULL; + uint32_t len = 0; + + /* Tiny stupid buffer to get the length of the path */ + if (!err) { + buffer = malloc (1); + if (!buffer) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + } + + /* Get the length of the path */ + if (!err) { + if (_NSGetExecutablePath (buffer, &len) != 0) { + char *temp = realloc (buffer, len + 1); + if (!temp) { + err = check_error (KIM_OUT_OF_MEMORY_ERR); + } else { + buffer = temp; + } + } + } + + /* Get the path */ + if (!err) { + if (_NSGetExecutablePath (buffer, &len) != 0) { + err = check_error (KIM_OUT_OF_MEMORY_ERR); + } else { + err = kim_string_copy (&path, buffer); + } + } + + if (buffer) { free (buffer); } + } + + if (!err) { + *out_path = path; + path = NULL; + } + + kim_string_free (&path); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_library_get_caller_name (kim_string *out_application_name) +{ + kim_error err = KIM_NO_ERROR; + kim_string name = NULL; + CFBundleRef bundle = CFBundleGetMainBundle (); + CFStringRef cfname = NULL; + + if (!err && !out_application_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err && bundle) { + cfname = CFBundleGetValueForInfoDictionaryKey (bundle, + kCFBundleNameKey); + + if (!cfname || CFGetTypeID (cfname) != CFStringGetTypeID ()) { + cfname = CFBundleGetValueForInfoDictionaryKey (bundle, + kCFBundleExecutableKey); + } + + if (cfname) { + cfname = CFStringCreateCopy (kCFAllocatorDefault, cfname); + } + } + + if (!err && !cfname) { + kim_string path = NULL; + CFURLRef cfpath = NULL; + CFURLRef cfpathnoext = NULL; + + err = kim_os_library_get_application_path (&path); + + if (!err) { + cfpath = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, + (const UInt8 *) path, + strlen (path), + 0); + + if (cfpath) { + cfpathnoext = CFURLCreateCopyDeletingPathExtension (kCFAllocatorDefault, + cfpath); + } + + if (cfpathnoext) { + cfname = CFURLCopyLastPathComponent (cfpathnoext); + } else { + cfname = CFURLCopyLastPathComponent (cfpath); + } + } + + if (cfpathnoext) { CFRelease (cfpathnoext); } + if (cfpath ) { CFRelease (cfpath); } + kim_string_free (&path); + } + + if (!err && cfname) { + err = kim_os_string_create_from_cfstring (&name, cfname); + } + + if (!err) { + *out_application_name = name; + name = NULL; + + } + + if (cfname) { CFRelease (cfname); } + kim_string_free (&name); + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_preferences.c b/krb5-1-7/src/kim/lib/mac/kim_os_preferences.c new file mode 100644 index 000000000..87700ef89 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_preferences.c @@ -0,0 +1,1073 @@ +/* + * $Header$ + * + * 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. + */ + +#include + +#include "kim_os_private.h" + +#define kim_os_preference_any_identity "KIM_IDENTITY_ANY" + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static CFStringRef kim_os_preferences_cfstring_for_key (kim_preference_key in_key) +{ + if (in_key == kim_preference_key_options) { + return CFSTR ("CredentialOptions"); + + } else if (in_key == kim_preference_key_lifetime) { + return CFSTR ("CredentialLifetime"); + + } else if (in_key == kim_preference_key_renewable) { + return CFSTR ("RenewableCredentials"); + + } else if (in_key == kim_preference_key_renewal_lifetime) { + return CFSTR ("CredentialRenewalLifetime"); + + } else if (in_key == kim_preference_key_forwardable) { + return CFSTR ("ForwardableCredentials"); + + } else if (in_key == kim_preference_key_proxiable) { + return CFSTR ("ProxiableCredentials"); + + } else if (in_key == kim_preference_key_addressless) { + return CFSTR ("AddresslessCredentials"); + + } else if (in_key == kim_preference_key_remember_options) { + return CFSTR ("RememberCredentialAttributes"); + + } else if (in_key == kim_preference_key_client_identity) { + return CFSTR ("ClientIdentity"); + + } else if (in_key == kim_preference_key_remember_client_identity) { + return CFSTR ("RememberClientIdentity"); + + } else if (in_key == kim_preference_key_favorites) { + return CFSTR ("FavoriteIdentities"); + + } else if (in_key == kim_preference_key_minimum_lifetime) { + return CFSTR ("MinimumLifetime"); + + } else if (in_key == kim_preference_key_maximum_lifetime) { + return CFSTR ("MaximumLifetime"); + + } else if (in_key == kim_preference_key_minimum_renewal_lifetime) { + return CFSTR ("MinimumRenewalLifetime"); + + } else if (in_key == kim_preference_key_maximum_renewal_lifetime) { + return CFSTR ("MaximumRenewalLifetime"); + + } + + return NULL; /* ignore unsupported keys */ +} + +/* ------------------------------------------------------------------------ */ + +static CFStringRef kim_os_preferences_compat_cfstring_for_key (kim_preference_key in_key) +{ + if (in_key == kim_preference_key_lifetime) { + return CFSTR ("KLDefaultTicketLifetime"); + + } else if (in_key == kim_preference_key_renewable) { + return CFSTR ("KLGetRenewableTickets"); + + } else if (in_key == kim_preference_key_renewal_lifetime) { + return CFSTR ("KLDefaultRenewableLifetime"); + + } else if (in_key == kim_preference_key_forwardable) { + return CFSTR ("KLDefaultForwardableTicket"); + + } else if (in_key == kim_preference_key_proxiable) { + return CFSTR ("KLGetProxiableTickets"); + + } else if (in_key == kim_preference_key_addressless) { + return CFSTR ("KLGetAddresslessTickets"); + + } else if (in_key == kim_preference_key_remember_options) { + return CFSTR ("KLRememberExtras"); + + } else if (in_key == kim_preference_key_client_identity) { + return CFSTR ("KLName"); + + } else if (in_key == kim_preference_key_remember_client_identity) { + return CFSTR ("KLRememberPrincipal"); + + } else if (in_key == kim_preference_key_favorites) { + return CFSTR ("KLFavoriteIdentities"); + + } else if (in_key == kim_preference_key_minimum_lifetime) { + return CFSTR ("KLMinimumTicketLifetime"); + + } else if (in_key == kim_preference_key_maximum_lifetime) { + return CFSTR ("KLMaximumTicketLifetime"); + + } else if (in_key == kim_preference_key_minimum_renewal_lifetime) { + return CFSTR ("KLMinimumRenewableLifetime"); + + } else if (in_key == kim_preference_key_maximum_renewal_lifetime) { + return CFSTR ("KLMaximumRenewableLifetime"); + + } + + return NULL; /* ignore unsupported keys */ +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_copy_value_for_file (CFStringRef in_key, + CFTypeID in_type, + CFStringRef in_file, + CFPropertyListRef *out_value) +{ + + kim_error err = KIM_NO_ERROR; + CFPropertyListRef value = NULL; + CFStringRef users[] = { kCFPreferencesCurrentUser, kCFPreferencesAnyUser, NULL }; + CFStringRef hosts[] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost, NULL }; + + if (!err && !in_key ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_file ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_value) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_count u, h; + + if (!kim_library_allow_home_directory_access()) { + users[0] = kCFPreferencesAnyUser; + users[1] = NULL; + } + + for (u = 0; !value && users[u]; u++) { + for (h = 0; !value && hosts[h]; h++) { + value = CFPreferencesCopyValue (in_key, in_file, users[u], hosts[h]); + } + } + + if (value && CFGetTypeID (value) != in_type) { + err = check_error (KIM_PREFERENCES_READ_ERR); + } + } + + + if (!err) { + *out_value = value; + value = NULL; + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_copy_value (kim_preference_key in_key, + CFTypeID in_type, + CFPropertyListRef *out_value) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef key = kim_os_preferences_cfstring_for_key (in_key); + + err = kim_os_preferences_copy_value_for_file (key, in_type, + KIM_PREFERENCES_FILE, + out_value); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_copy_value_compat (kim_preference_key in_key, + CFTypeID in_type, + CFPropertyListRef *out_value) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef key = kim_os_preferences_compat_cfstring_for_key (in_key); + + err = kim_os_preferences_copy_value_for_file (key, in_type, + KLL_PREFERENCES_FILE, + out_value); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_set_value (kim_preference_key in_key, + CFPropertyListRef in_value) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef key = NULL; + + /* in_value may be NULL if removing the key */ + + if (!err) { + key = kim_os_preferences_cfstring_for_key (in_key); + } + + if (!err && key) { + kim_boolean homedir_ok = kim_library_allow_home_directory_access(); + CFStringRef user = homedir_ok ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef host = homedir_ok ? kCFPreferencesAnyHost : kCFPreferencesCurrentHost; + + CFPreferencesSetValue (key, in_value, KIM_PREFERENCES_FILE, user, host); + if (!CFPreferencesSynchronize (KIM_PREFERENCES_FILE, user, host)) { + err = check_error (KIM_PREFERENCES_WRITE_ERR); + } + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_get_identity_for_key (kim_preference_key in_key, + kim_identity in_hardcoded_default, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + CFStringRef value = NULL; + + if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_preferences_copy_value (in_key, CFStringGetTypeID (), + (CFPropertyListRef *) &value); + + } + + if (!err && !value) { + err = kim_os_preferences_copy_value_compat (in_key, CFStringGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err) { + if (value) { + err = kim_os_string_create_from_cfstring (&string, value); + + if (!err) { + if (!strcmp (kim_os_preference_any_identity, string)) { + *out_identity = KIM_IDENTITY_ANY; + + } else { + err = kim_identity_create_from_string (out_identity, string); + } + } + } else { + err = kim_identity_copy (out_identity, in_hardcoded_default); + } + } + + kim_string_free (&string); + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_set_identity_for_key (kim_preference_key in_key, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef value = NULL; + kim_string string = NULL; + + /* in_identity can be KIM_IDENTITY_ANY */ + + if (!err) { + if (in_identity) { + err = kim_identity_get_string (in_identity, &string); + + } else { + err = kim_string_copy (&string, kim_os_preference_any_identity); + } + } + + if (!err) { + err = kim_os_string_get_cfstring (string, &value); + } + + if (!err) { + err = kim_os_preferences_set_value (in_key, value); + } + + if (value) { CFRelease (value); } + kim_string_free (&string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_get_lifetime_for_key (kim_preference_key in_key, + kim_lifetime in_hardcoded_default, + kim_lifetime *out_lifetime) +{ + kim_error err = KIM_NO_ERROR; + CFNumberRef value = NULL; + + if (!err && !out_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_preferences_copy_value (in_key, CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err && !value) { + err = kim_os_preferences_copy_value_compat (in_key, CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err) { + if (value) { + SInt32 number; // CFNumbers are signed so we need to cast + if (CFNumberGetValue (value, kCFNumberSInt32Type, &number) != TRUE) { + err = KIM_OUT_OF_MEMORY_ERR; + } else { + *out_lifetime = number; + } + } else { + *out_lifetime = in_hardcoded_default; + } + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_set_lifetime_for_key (kim_preference_key in_key, + kim_lifetime in_lifetime) +{ + kim_error err = KIM_NO_ERROR; + CFNumberRef value = NULL; + SInt32 number = (SInt32) in_lifetime; + + if (!err) { + value = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &number); + if (!value) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + err = kim_os_preferences_set_value (in_key, value); + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_get_boolean_for_key (kim_preference_key in_key, + kim_boolean in_hardcoded_default, + kim_boolean *out_boolean) +{ + kim_error err = KIM_NO_ERROR; + CFBooleanRef value = NULL; + + if (!err && !out_boolean) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_preferences_copy_value (in_key, CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err && !value) { + err = kim_os_preferences_copy_value_compat (in_key, CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err) { + if (value) { + *out_boolean = CFBooleanGetValue (value); + } else { + *out_boolean = in_hardcoded_default; + } + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_set_boolean_for_key (kim_preference_key in_key, + kim_boolean in_boolean) +{ + kim_error err = KIM_NO_ERROR; + CFBooleanRef value = in_boolean ? kCFBooleanTrue : kCFBooleanFalse; + + if (!err) { + err = kim_os_preferences_set_value (in_key, value); + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_copy_value_for_dict_key (CFDictionaryRef in_dictionary, + kim_preference_key in_key, + CFTypeID in_type, + CFPropertyListRef *out_value) +{ + kim_error err = KIM_NO_ERROR; + CFPropertyListRef value = NULL; + + if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_value ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + CFStringRef key = kim_os_preferences_cfstring_for_key (in_key); + + value = CFDictionaryGetValue (in_dictionary, key); + if (value && CFGetTypeID (value) != in_type) { + err = check_error (KIM_PREFERENCES_READ_ERR); + } + } + + if (!err) { + *out_value = value; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_set_value_for_dict_key (CFMutableDictionaryRef in_dictionary, + kim_preference_key in_key, + CFPropertyListRef in_value) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_value ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + CFStringRef key = kim_os_preferences_cfstring_for_key (in_key); + + CFDictionarySetValue (in_dictionary, key, in_value); + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_dictionary_to_options (CFDictionaryRef in_dictionary, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = KIM_OPTIONS_DEFAULT; + kim_boolean found_options = 0; + + if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_create_empty (&options); + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_renewable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_renewable (options, CFBooleanGetValue (value)); + } + } + + if (!err) { + CFNumberRef value = NULL; + SInt32 lifetime; // CFNumbers are signed so we need to cast + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_lifetime, + CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, + &lifetime)) { + found_options = 1; + err = kim_options_set_lifetime (options, lifetime); + } + } + + if (!err) { + CFNumberRef value = NULL; + SInt32 lifetime; // CFNumbers are signed so we need to cast + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_renewal_lifetime, + CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, + &lifetime)) { + found_options = 1; + err = kim_options_set_renewal_lifetime (options, lifetime); + } } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_forwardable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_forwardable (options, CFBooleanGetValue (value)); + } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_proxiable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_proxiable (options, CFBooleanGetValue (value)); + } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_for_dict_key (in_dictionary, + kim_preference_key_addressless, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_addressless (options, CFBooleanGetValue (value)); + } + } + + if (!err && !found_options) { + kim_options_free (&options); + options = KIM_OPTIONS_DEFAULT; + } + + if (!err) { + *out_options = options; + options = NULL; + } + + kim_options_free (&options); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_options_to_dictionary (kim_options in_options, + CFMutableDictionaryRef io_dictionary) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !io_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + CFNumberRef value = NULL; + kim_lifetime lifetime; + + err = kim_options_get_lifetime (in_options, &lifetime); + + if (!err) { + SInt32 number = (SInt32) lifetime; + + value = CFNumberCreate (kCFAllocatorDefault, + kCFNumberSInt32Type, &number); + if (!value) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_lifetime, + value); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + kim_boolean boolean; + + err = kim_options_get_renewable (in_options, &boolean); + + if (!err) { + CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse; + + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_renewable, + value); + } + } + + if (!err) { + CFNumberRef value = NULL; + kim_lifetime lifetime; + + err = kim_options_get_renewal_lifetime (in_options, &lifetime); + + if (!err) { + SInt32 number = (SInt32) lifetime; + + value = CFNumberCreate (kCFAllocatorDefault, + kCFNumberSInt32Type, &number); + if (!value) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_renewal_lifetime, + value); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + kim_boolean boolean; + + err = kim_options_get_forwardable (in_options, &boolean); + + if (!err) { + CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse; + + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_forwardable, + value); + } + } + + if (!err) { + kim_boolean boolean; + + err = kim_options_get_proxiable (in_options, &boolean); + + if (!err) { + CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse; + + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_proxiable, + value); + } + } + + if (!err) { + kim_boolean boolean; + + err = kim_options_get_addressless (in_options, &boolean); + + if (!err) { + CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse; + + err = kim_os_preferences_set_value_for_dict_key (io_dictionary, + kim_preference_key_addressless, + value); + } + } + + return check_error (err); +} + + + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_preferences_get_options_compat (kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + kim_options options = KIM_OPTIONS_DEFAULT; + kim_boolean found_options = 0; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_options_create_empty (&options); + } + + if (!err) { + CFNumberRef value = NULL; + SInt32 lifetime; // CFNumbers are signed so we need to cast + + err = kim_os_preferences_copy_value_compat (kim_preference_key_lifetime, + CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, + &lifetime)) { + found_options = 1; + err = kim_options_set_lifetime (options, lifetime); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_compat (kim_preference_key_renewable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_renewable (options, CFBooleanGetValue (value)); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + CFNumberRef value = NULL; + SInt32 lifetime; // CFNumbers are signed so we need to cast + + err = kim_os_preferences_copy_value_compat (kim_preference_key_renewal_lifetime, + CFNumberGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, + &lifetime)) { + found_options = 1; + err = kim_options_set_renewal_lifetime (options, lifetime); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_compat (kim_preference_key_forwardable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_forwardable (options, CFBooleanGetValue (value)); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_compat (kim_preference_key_proxiable, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_proxiable (options, CFBooleanGetValue (value)); + } + + if (value) { CFRelease (value); } + } + + if (!err) { + CFBooleanRef value = NULL; + + err = kim_os_preferences_copy_value_compat (kim_preference_key_addressless, + CFBooleanGetTypeID (), + (CFPropertyListRef *) &value); + + if (!err && value) { + found_options = 1; + err = kim_options_set_addressless (options, CFBooleanGetValue (value)); + } + + if (value) { CFRelease (value); } + } + + if (!err && !found_options) { + kim_options_free (&options); + options = KIM_OPTIONS_DEFAULT; + } + + if (!err) { + *out_options = options; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_get_options_for_key (kim_preference_key in_key, + kim_options *out_options) +{ + kim_error err = KIM_NO_ERROR; + CFDictionaryRef dictionary = NULL; + kim_options options = KIM_OPTIONS_DEFAULT; + + if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_preferences_copy_value (in_key, CFDictionaryGetTypeID (), + (CFPropertyListRef *) &dictionary); + + if (!err && dictionary) { + err = kim_os_preferences_dictionary_to_options (dictionary, &options); + } + } + + if (!err && !dictionary) { + err = kim_os_preferences_get_options_compat (&options); + } + + if (!err) { + *out_options = options; + } + + if (dictionary) { CFRelease (dictionary); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_set_options_for_key (kim_preference_key in_key, + kim_options in_options) +{ + kim_error err = KIM_NO_ERROR; + CFMutableDictionaryRef dictionary = NULL; + + /* in_options may be KIM_OPTIONS_DEFAULT, in which case we empty the dict */ + + if (!err && in_options) { + dictionary = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (!dictionary) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + + if (!err) { + err = kim_os_preferences_options_to_dictionary (in_options, dictionary); + } + } + + if (!err) { + /* NULL dictioray will remove any entry for this key */ + err = kim_os_preferences_set_value (in_key, dictionary); + } + + if (dictionary) { CFRelease (dictionary); } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_preferences_get_favorites_for_key (kim_preference_key in_key, + kim_favorites io_favorites) +{ + kim_error err = KIM_NO_ERROR; + CFArrayRef value = NULL; + + if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_preferences_copy_value (in_key, CFArrayGetTypeID (), + (CFPropertyListRef *) &value); + } + + if (!err && value) { + if (!value || CFArrayGetCount (value) < 1) { + err = kim_favorites_remove_all_identities (io_favorites); + + } else { + CFIndex count = CFArrayGetCount (value); + CFIndex i; + + for (i = 0; !err && i < count; i++) { + CFDictionaryRef dictionary = NULL; + CFStringRef cfstring = NULL; + + dictionary = (CFDictionaryRef) CFArrayGetValueAtIndex (value, i); + if (!dictionary || CFGetTypeID (dictionary) != CFDictionaryGetTypeID ()) { + err = check_error (KIM_PREFERENCES_READ_ERR); + } + + if (!err) { + err = kim_os_preferences_copy_value_for_dict_key (dictionary, + kim_preference_key_client_identity, + CFStringGetTypeID (), + (CFPropertyListRef *) &cfstring); + } + + if (!err && cfstring) { + kim_string string = NULL; + kim_identity identity = NULL; + kim_options options = KIM_OPTIONS_DEFAULT; + + err = kim_os_string_create_from_cfstring (&string, cfstring); + + if (!err) { + err = kim_identity_create_from_string (&identity, string); + } + + if (!err && (CFDictionaryGetCount (dictionary) > 1)) { + err = kim_os_preferences_dictionary_to_options (dictionary, + &options); + } + + if (!err) { + err = kim_favorites_add_identity (io_favorites, identity, + options); + } + + kim_string_free (&string); + kim_options_free (&options); + kim_identity_free (&identity); + } + } + + if (err) { + kim_favorites_remove_all_identities (io_favorites); + } + } + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ +kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key, + kim_favorites in_favorites) +{ + kim_error err = KIM_NO_ERROR; + kim_count count = 0; + CFMutableArrayRef array = NULL; + + if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_favorites_get_number_of_identities (in_favorites, &count); + } + + if (!err) { + array = CFArrayCreateMutable (kCFAllocatorDefault, count, + &kCFTypeArrayCallBacks); + if (!array) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + kim_count i; + + for (i = 0; !err && i < count; i++) { + kim_identity identity = NULL; + kim_options options = NULL; + kim_string string = NULL; + CFStringRef cfstring = NULL; + CFMutableDictionaryRef dictionary = NULL; + + err = kim_favorites_get_identity_at_index (in_favorites, i, + &identity, + &options); + + if (!err) { + err = kim_identity_get_string (identity, &string); + } + + if (!err) { + err = kim_os_string_get_cfstring (string, &cfstring); + } + + if (!err) { + dictionary = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (!dictionary) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + } + + if (!err) { + err = kim_os_preferences_set_value_for_dict_key (dictionary, + kim_preference_key_client_identity, + cfstring); + } + + if (!err && options) { + err = kim_os_preferences_options_to_dictionary (options, + dictionary); + } + + if (!err) { + CFArrayAppendValue (array, dictionary); + } + + if (dictionary) { CFRelease (dictionary); } + if (cfstring ) { CFRelease (cfstring); } + kim_string_free (&string); + kim_options_free (&options); + kim_identity_free (&identity); + } + } + + if (!err) { + err = kim_os_preferences_set_value (in_key, array); + } + + if (array) { CFRelease (array); } + + return check_error (err); +} + diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_private.h b/krb5-1-7/src/kim/lib/mac/kim_os_private.h new file mode 100644 index 000000000..f14440df4 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_private.h @@ -0,0 +1,56 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef KIM_OS_PRIVATE_H +#define KIM_OS_PRIVATE_H + +#include +#include "kim_private.h" + +#define kim_os_agent_bundle_id "edu.mit.Kerberos.KerberosAgent" + +#define KIM_PREFERENCES_FILE CFSTR("edu.mit.Kerberos.IdentityManagement") +#define KLL_PREFERENCES_FILE CFSTR("edu.mit.Kerberos.KerberosLogin") +#define KA_PREFERENCES_FILE CFSTR("edu.mit.Kerberos.KerberosAgent") + +kim_error kim_os_library_lock_for_bundle_lookup (void); +kim_error kim_os_library_unlock_for_bundle_lookup (void); + +kim_error kim_os_library_get_application_path (kim_string *out_path); + +kim_error kim_os_string_create_from_cfstring (kim_string *out_string, + CFStringRef in_cfstring); + +kim_error kim_os_string_get_cfstring (kim_string in_string, + CFStringRef *out_cfstring); + +kim_error kim_os_string_compare_to_cfstring (kim_string in_string, + CFStringRef in_compare_to_cfstring, + kim_comparison *out_comparison); + +kim_error kim_os_library_get_application_path (kim_string *out_path); + +#endif /* KIM_PRIVATE_H */ diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_selection_hints.c b/krb5-1-7/src/kim/lib/mac/kim_os_selection_hints.c new file mode 100644 index 000000000..bc1a64868 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_selection_hints.c @@ -0,0 +1,536 @@ +/* + * $Header$ + * + * 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. + */ + +#define KIM_SELECTION_HINTS_FILE CFSTR("edu.mit.Kerberos.SelectionHints") + +#define KIM_SELECTION_HINTS_ARRAY CFSTR("Hints") + +#define KIM_SERVICE_IDENTITY_HINT CFSTR("KIMServiceIdentityHint") +#define KIM_APPLICATION_ID_HINT CFSTR("KIMApplicationIDHint") +#define KIM_USER_HINT CFSTR("KIMUserHint") +#define KIM_CLIENT_REALM_HINT CFSTR("KIMClientRealmHint") +#define KIM_SERVICE_HINT CFSTR("KIMServiceHint") +#define KIM_SERVICE_REALM_HINT CFSTR("KIMServiceRealmHint") +#define KIM_SERVER_HINT CFSTR("KIMServerHint") +#define KIM_IDENTITY_HINT CFSTR("KIMIdentityHint") + +#define KIM_MAX_HINTS 8 /* the number of hint types above */ + +#include "kim_os_private.h" + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_selection_hints_get_selection_hints_array (CFArrayRef *out_selection_hints_array) +{ + kim_error err = KIM_NO_ERROR; + CFPropertyListRef value = NULL; + CFStringRef users[] = { kCFPreferencesCurrentUser, kCFPreferencesAnyUser, NULL }; + CFStringRef hosts[] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost, NULL }; + + if (!err && !out_selection_hints_array) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_count u, h; + + if (!kim_library_allow_home_directory_access()) { + users[0] = kCFPreferencesAnyUser; + users[1] = NULL; + } + + for (u = 0; !value && users[u]; u++) { + for (h = 0; !value && hosts[h]; h++) { + value = CFPreferencesCopyValue (KIM_SELECTION_HINTS_ARRAY, + KIM_SELECTION_HINTS_FILE, + users[u], hosts[h]); + } + } + + if (value && CFGetTypeID (value) != CFArrayGetTypeID ()) { + err = check_error (KIM_PREFERENCES_READ_ERR); + } + } + + if (!err) { + *out_selection_hints_array = value; + value = NULL; + } + + if (value) { CFRelease (value); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_selection_hints_set_selection_hints_array (CFArrayRef in_selection_hints_array) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints_array) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + kim_boolean homedir_ok = kim_library_allow_home_directory_access(); + CFStringRef user = homedir_ok ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef host = homedir_ok ? kCFPreferencesAnyHost : kCFPreferencesCurrentHost; + + CFPreferencesSetValue (KIM_SELECTION_HINTS_ARRAY, in_selection_hints_array, + KIM_SELECTION_HINTS_FILE, user, host); + if (!CFPreferencesSynchronize (KIM_SELECTION_HINTS_FILE, user, host)) { + err = check_error (KIM_PREFERENCES_WRITE_ERR); + } + } + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_selection_hints_create_dictionary (kim_selection_hints in_selection_hints, + kim_identity in_identity, + CFDictionaryRef *out_hints_dictionary) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints_preference_strings preference_strings = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + kim_string identity_string = NULL; + CFStringRef keys[KIM_MAX_HINTS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + CFStringRef values[KIM_MAX_HINTS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + CFIndex i = 0; + + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_hints_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_get_preference_strings (in_selection_hints, &preference_strings); + } + + if (!err) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + keys[i] = KIM_APPLICATION_ID_HINT; + err = kim_os_string_get_cfstring (preference_strings.application_identifier, &values[i]); + } + + if (!err) { + keys[++i] = KIM_IDENTITY_HINT; + err = kim_os_string_get_cfstring (identity_string, &values[i]); + } + + if (!err && preference_strings.service_identity) { + keys[++i] = KIM_SERVICE_IDENTITY_HINT; + err = kim_os_string_get_cfstring (preference_strings.service_identity, &values[i]); + } + + if (!err && preference_strings.user) { + keys[++i] = KIM_USER_HINT; + err = kim_os_string_get_cfstring (preference_strings.user, &values[i]); + } + + if (!err && preference_strings.client_realm) { + keys[++i] = KIM_CLIENT_REALM_HINT; + err = kim_os_string_get_cfstring (preference_strings.client_realm, &values[i]); + } + + if (!err && preference_strings.service) { + keys[++i] = KIM_SERVICE_HINT; + err = kim_os_string_get_cfstring (preference_strings.service, &values[i]); + } + + if (!err && preference_strings.service_realm) { + keys[++i] = KIM_SERVICE_REALM_HINT; + err = kim_os_string_get_cfstring (preference_strings.service_realm, &values[i]); + } + + if (!err && preference_strings.server) { + keys[++i] = KIM_SERVER_HINT; + err = kim_os_string_get_cfstring (preference_strings.server, &values[i]); + } + + if (!err) { + *out_hints_dictionary = CFDictionaryCreate (kCFAllocatorDefault, + (const void **) keys, + (const void **) values, + i+1, /* number of hints */ + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + for (i = 0; i < KIM_MAX_HINTS; i++) { if (values[i]) { CFRelease (values[i]); } } + kim_string_free (&identity_string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_boolean kim_os_selection_hints_compare_hint (kim_string in_string, + CFStringRef in_value) +{ + kim_boolean equal = 0; + + if (!in_string && !in_value) { + equal = 1; + + } else if (in_string && in_value) { + if (CFGetTypeID (in_value) == CFStringGetTypeID ()) { + kim_comparison comparison; + + kim_error err = kim_os_string_compare_to_cfstring (in_string, in_value, + &comparison); + + if (!err && kim_comparison_is_equal_to (comparison)) { + equal = 1; + } + } else { + kim_debug_printf ("%s: Malformed string in hints dictionary.", __FUNCTION__); + } + } + + return equal; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_selection_hints_compare_to_dictionary (kim_selection_hints in_selection_hints, + CFDictionaryRef in_hints_dictionary, + kim_boolean *out_hints_equal) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints_preference_strings preference_strings = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + kim_boolean hints_equal = 1; + + if (!err && !in_selection_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_hints_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_hints_equal ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_selection_hints_get_preference_strings (in_selection_hints, &preference_strings); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.application_identifier, + CFDictionaryGetValue (in_hints_dictionary, + KIM_APPLICATION_ID_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.service_identity, + CFDictionaryGetValue (in_hints_dictionary, + KIM_SERVICE_IDENTITY_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.user, + CFDictionaryGetValue (in_hints_dictionary, + KIM_USER_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.client_realm, + CFDictionaryGetValue (in_hints_dictionary, + KIM_CLIENT_REALM_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.service, + CFDictionaryGetValue (in_hints_dictionary, + KIM_SERVICE_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.service_realm, + CFDictionaryGetValue (in_hints_dictionary, + KIM_SERVICE_REALM_HINT)); + } + + if (!err && hints_equal) { + hints_equal = kim_os_selection_hints_compare_hint (preference_strings.server, + CFDictionaryGetValue (in_hints_dictionary, + KIM_SERVER_HINT)); + } + + if (!err) { + *out_hints_equal = hints_equal; + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static kim_error kim_os_selection_hints_get_dictionary_identity (CFDictionaryRef in_dictionary, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef identity_cfstr = NULL; + kim_string identity_string = NULL; + + identity_cfstr = CFDictionaryGetValue (in_dictionary, KIM_IDENTITY_HINT); + if (!identity_cfstr || CFGetTypeID (identity_cfstr) != CFStringGetTypeID ()) { + kim_debug_printf ("%s: Malformed hints dictionary (invalid identity).", __FUNCTION__); + err = check_error (KIM_PREFERENCES_READ_ERR); + } + + if (!err) { + err = kim_os_string_create_from_cfstring (&identity_string, identity_cfstr); + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity_string); + } + + kim_string_free (&identity_string); + + return check_error (err); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_selection_hints_lookup_identity (kim_selection_hints in_selection_hints, + kim_identity *out_identity) +{ + kim_error err = KIM_NO_ERROR; + CFArrayRef hints_array = NULL; + CFIndex i = 0; + CFIndex count = 0; + kim_boolean found = 0; + CFDictionaryRef found_dictionary = NULL; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_selection_hints_get_selection_hints_array (&hints_array); + } + + if (!err && hints_array) { + count = CFArrayGetCount (hints_array); + } + + for (i = 0; !err && !found && i < count; i++) { + CFDictionaryRef dictionary = NULL; + + dictionary = CFArrayGetValueAtIndex (hints_array, i); + if (!dictionary) { err = KIM_OUT_OF_MEMORY_ERR; } + + if (!err && CFGetTypeID (dictionary) != CFDictionaryGetTypeID ()) { + kim_debug_printf ("%s: Malformed entry in hints array.", __FUNCTION__); + continue; /* skip entries which aren't dictionaries */ + } + + if (!err) { + err = kim_os_selection_hints_compare_to_dictionary (in_selection_hints, + dictionary, + &found); + } + + if (!err && found) { + found_dictionary = dictionary; + } + } + + if (!err && found) { + err = kim_os_selection_hints_get_dictionary_identity (found_dictionary, + out_identity); + } + + if (hints_array) { CFRelease (hints_array); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_selection_hints_remember_identity (kim_selection_hints in_selection_hints, + kim_identity in_identity) +{ + kim_error err = KIM_NO_ERROR; + CFArrayRef old_hints_array = NULL; + CFMutableArrayRef new_hints_array = NULL; + CFIndex count = 0; + CFIndex i = 0; + kim_boolean hint_already_exists = 0; + kim_boolean hints_array_changed = 0; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_selection_hints_get_selection_hints_array (&old_hints_array); + } + + if (!err) { + if (old_hints_array) { + new_hints_array = CFArrayCreateMutableCopy (kCFAllocatorDefault, 0, + old_hints_array); + } else { + new_hints_array = CFArrayCreateMutable (kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + } + if (!new_hints_array) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + count = CFArrayGetCount (new_hints_array); + } + + for (i = 0; !err && i < count; i++) { + CFDictionaryRef dictionary = NULL; + kim_identity identity = NULL; + kim_boolean hints_equal = 0; + + dictionary = CFArrayGetValueAtIndex (new_hints_array, i); + if (!dictionary) { err = KIM_OUT_OF_MEMORY_ERR; } + + if (!err && CFGetTypeID (dictionary) != CFDictionaryGetTypeID ()) { + kim_debug_printf ("%s: Malformed entry in hints array.", __FUNCTION__); + continue; /* skip entries which aren't dictionaries */ + } + + if (!err) { + err = kim_os_selection_hints_compare_to_dictionary (in_selection_hints, + dictionary, + &hints_equal); + } + + if (!err && hints_equal) { + kim_comparison comparison; + + err = kim_os_selection_hints_get_dictionary_identity (dictionary, + &identity); + + if (!err) { + err = kim_identity_compare (in_identity, identity, &comparison); + } + + if (!err) { + if (kim_comparison_is_equal_to (comparison) && !hint_already_exists) { + hint_already_exists = 1; + } else { + CFArrayRemoveValueAtIndex (new_hints_array, i); + i--; /* back up one index so we don't skip */ + count = CFArrayGetCount (new_hints_array); /* count changed */ + hints_array_changed = 1; + } + } + + kim_identity_free (&identity); + } + } + + if (!err && !hint_already_exists) { + CFDictionaryRef new_hint_dictionary = NULL; + + err = kim_os_selection_hints_create_dictionary (in_selection_hints, + in_identity, + &new_hint_dictionary); + + if (!err) { + CFArrayInsertValueAtIndex (new_hints_array, 0, new_hint_dictionary); + hints_array_changed = 1; + } + + if (new_hint_dictionary) { CFRelease (new_hint_dictionary); } + } + + if (!err && hints_array_changed) { + err = kim_os_selection_hints_set_selection_hints_array (new_hints_array); + } + + if (new_hints_array ) { CFRelease (new_hints_array); } + if (old_hints_array ) { CFRelease (old_hints_array); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_selection_hints_forget_identity (kim_selection_hints in_selection_hints) +{ + kim_error err = KIM_NO_ERROR; + CFArrayRef old_hints_array = NULL; + CFMutableArrayRef new_hints_array = NULL; + CFIndex count = 0; + CFIndex i = 0; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_selection_hints_get_selection_hints_array (&old_hints_array); + } + + if (!err) { + new_hints_array = CFArrayCreateMutableCopy (kCFAllocatorDefault, 0, + old_hints_array); + if (!new_hints_array) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + count = CFArrayGetCount (new_hints_array); + } + + for (i = 0; !err && i < count; i++) { + CFDictionaryRef dictionary = NULL; + kim_boolean hints_equal = 0; + + dictionary = CFArrayGetValueAtIndex (new_hints_array, i); + if (!dictionary) { err = KIM_OUT_OF_MEMORY_ERR; } + + if (!err && CFGetTypeID (dictionary) != CFDictionaryGetTypeID ()) { + kim_debug_printf ("%s: Malformed entry in hints array.", __FUNCTION__); + continue; /* skip entries which aren't dictionaries */ + } + + if (!err) { + err = kim_os_selection_hints_compare_to_dictionary (in_selection_hints, + dictionary, + &hints_equal); + } + + if (!err && hints_equal) { + CFArrayRemoveValueAtIndex (new_hints_array, i); + i--; /* back up one index so we don't skip */ + count = CFArrayGetCount (new_hints_array); /* count changed */ + } + } + + if (!err) { + err = kim_os_selection_hints_set_selection_hints_array (new_hints_array); + } + + if (new_hints_array) { CFRelease (new_hints_array); } + + return check_error (err); +} + diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_string.c b/krb5-1-7/src/kim/lib/mac/kim_os_string.c new file mode 100644 index 000000000..96573eec9 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_string.c @@ -0,0 +1,237 @@ +/* + * $Header$ + * + * 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. + */ + +#include + +#include "kim_os_private.h" + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_string_create_localized (kim_string *out_string, + kim_string in_string) +{ + kim_error lock_err = kim_os_library_lock_for_bundle_lookup (); + kim_error err = lock_err; + kim_string string = NULL; + CFStringRef cfkey = NULL; + + if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_get_cfstring (in_string, &cfkey); + } + + if (!err && kim_library_allow_home_directory_access ()) { + CFStringRef cfstring = NULL; + CFBundleRef framework = CFBundleGetBundleWithIdentifier (CFSTR ("edu.mit.Kerberos")); + CFBundleRef main_bundle = CFBundleGetMainBundle (); + + if (framework) { + cfstring = CFCopyLocalizedStringFromTableInBundle (cfkey, + CFSTR ("InfoPlist"), + framework, + ""); + } + + if (main_bundle && !cfstring) { + cfstring = CFCopyLocalizedStringFromTableInBundle (cfkey, + CFSTR ("InfoPlist"), + main_bundle, + ""); + } + + if (!err && cfstring) { + err = kim_os_string_create_from_cfstring (&string, cfstring); + } + + if (cfstring) { CFRelease (cfstring); } + } + + if (!err && !string) { + err = kim_string_copy (&string, in_string); + } + + if (!err) { + *out_string = string; + string = NULL; + } + + if (cfkey) { CFRelease (cfkey); } + kim_string_free (&string); + + if (!lock_err) { kim_os_library_unlock_for_bundle_lookup (); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_string_create_from_cfstring (kim_string *out_string, + CFStringRef in_cfstring) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + CFIndex length = 0; + + if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_cfstring) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + char *ptr = NULL; + + /* check if in_cfstring is a C string internally so we can + * avoid using CFStringGetMaximumSizeForEncoding which is wasteful */ + ptr = (char *) CFStringGetCStringPtr(in_cfstring, + kCFStringEncodingUTF8); + if (ptr) { + string = strdup (ptr); + if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + + } else { + length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (in_cfstring), + kCFStringEncodingUTF8) + 1; + + string = (char *) calloc (length, sizeof (char)); + if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } + + if (!err) { + if (!CFStringGetCString (in_cfstring, + (char *) string, + length, + kCFStringEncodingUTF8)) { + err = KIM_OUT_OF_MEMORY_ERR; + } + } + } + } + + + if (!err) { + *out_string = string; + string = NULL; + } + + kim_string_free (&string); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_string_get_cfstring (kim_string in_string, + CFStringRef *out_cfstring) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef cfstring = NULL; + + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_cfstring) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + cfstring = CFStringCreateWithCString (kCFAllocatorDefault, + in_string, + kCFStringEncodingUTF8); + if (!cfstring) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + *out_cfstring = cfstring; + cfstring = NULL; + } + + if (cfstring) { CFRelease (cfstring); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_string_compare (kim_string in_string, + kim_string in_compare_to_string, + kim_boolean in_case_insensitive, + kim_comparison *out_comparison) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef cfstring = NULL; + CFStringRef compare_to_cfstring = NULL; + + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_compare_to_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_comparison ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_get_cfstring (in_string, + &cfstring); + } + + if (!err) { + err = kim_os_string_get_cfstring (in_compare_to_string, + &compare_to_cfstring); + } + + if (!err) { + CFOptionFlags options = (in_case_insensitive ? + 1 : kCFCompareCaseInsensitive); + + /* Returned CFComparisonResult is compatible with kim_comparison_t */ + *out_comparison = CFStringCompare (cfstring, + compare_to_cfstring, + options); + } + + if (cfstring ) { CFRelease (cfstring); } + if (compare_to_cfstring) { CFRelease (compare_to_cfstring); } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_string_compare_to_cfstring (kim_string in_string, + CFStringRef in_compare_to_cfstring, + kim_comparison *out_comparison) +{ + kim_error err = KIM_NO_ERROR; + CFStringRef cfstring = NULL; + + if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_compare_to_cfstring) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_comparison ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_os_string_get_cfstring (in_string, &cfstring); + } + + if (!err) { + /* Returned CFComparisonResult is compatible with kim_comparison_t */ + *out_comparison = CFStringCompare (cfstring, in_compare_to_cfstring, 0); + } + + if (cfstring) { CFRelease (cfstring); } + + return check_error (err); +} diff --git a/krb5-1-7/src/kim/lib/mac/kim_os_ui_gui.c b/krb5-1-7/src/kim/lib/mac/kim_os_ui_gui.c new file mode 100644 index 000000000..6e1c5cef1 --- /dev/null +++ b/krb5-1-7/src/kim/lib/mac/kim_os_ui_gui.c @@ -0,0 +1,563 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KIM_BUILTIN_UI + +#include "kim_os_private.h" + +#include "k5_mig_client.h" + +#include +#include +#include + +/* ------------------------------------------------------------------------ */ + +static inline int32_t kim_os_ui_gui_send_request (int32_t in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream) +{ + return k5_ipc_send_request (kim_os_agent_bundle_id, + in_launch_server, + in_request_stream, + out_reply_stream); +} + + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_init (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + kim_string name = NULL; + kim_string path = NULL; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_library_get_application_name (&name); + } + + if (!err) { + err = kim_os_library_get_application_path (&path); + } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "init"); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, getpid()); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, name ? name : ""); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, path ? path : ""); + } + + if (!err) { + err = kim_os_ui_gui_send_request (1 /* launch server */, + request, + &reply); + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + io_context->tcontext = NULL; + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + kim_string_free (&name); + kim_string_free (&path); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_enter_identity (kim_ui_context *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *identity_string = NULL; + kim_identity identity = NULL; + uint32_t change_password = 0; + + if (!err && !io_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "enter_identity"); + } + + if (!err) { + err = kim_options_write_to_stream (io_options, request); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (reply, &change_password); + } + + if (!err) { + err = kim_options_read_from_stream (io_options, reply); + } + + if (!err) { + err = kim_identity_create_from_string (&identity, identity_string); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + *out_change_password = change_password; + } + + kim_identity_free (&identity); + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *identity_string = NULL; + kim_options options = NULL; + kim_identity identity = NULL; + uint32_t change_password = 0; + + if (!err && !io_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "select_identity"); + } + + if (!err) { + err = kim_selection_hints_write_to_stream (io_hints, request); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &identity_string); + } + + if (!err) { + err = kim_identity_create_from_string (&identity, identity_string); + } + + if (!err) { + err = k5_ipc_stream_read_uint32 (reply, &change_password); + } + + if (!err) { + err = kim_options_create_from_stream (&options, reply); + } + + if (!err) { + err = kim_selection_hints_set_options (io_hints, options); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + *out_change_password = change_password; + } + + kim_identity_free (&identity); + kim_options_free (&options); + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_title, in_message or in_description may be NULL */ + + if (!err) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "auth_prompt"); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, identity_string); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_type); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_allow_save_reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_hide_reply); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, + in_title ? in_title : ""); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, + in_message ? in_message : ""); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, + in_description ? in_description : ""); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, out_reply); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (reply, out_save_reply); + } + + kim_string_free (&identity_string); + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_vfy_password) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + char *old_password = NULL; + char *new_password = NULL; + char *vfy_password = NULL; + + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_old_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_new_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_vfy_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "change_password"); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, identity_string); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_old_password_expired); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &old_password); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &new_password); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &vfy_password); + } + + if (!err) { + *out_old_password = (char *) old_password; + old_password = NULL; + *out_new_password = (char *) new_password; + new_password = NULL; + *out_vfy_password = (char *) vfy_password; + vfy_password = NULL; + } + + kim_string_free (&identity_string); + k5_ipc_stream_free_string (old_password); + k5_ipc_stream_free_string (new_password); + k5_ipc_stream_free_string (vfy_password); + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + err = kim_identity_get_string (in_identity, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "handle_error"); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, identity_string); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_error); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_error_message); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_error_description); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + kim_string_free (&identity_string); + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +void kim_os_ui_gui_free_string (kim_ui_context *in_context, + char **io_string) +{ + kim_string_free ((kim_string *) io_string); +} + +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_fini (kim_ui_context *io_context) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "fini"); + } + + if (!err) { + err = kim_os_ui_gui_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + + return check_error (err); +} + +#endif /* KIM_BUILTIN_UI */ diff --git a/krb5-1-7/src/kim/test/main.c b/krb5-1-7/src/kim/test/main.c new file mode 100644 index 000000000..e3efbd7f6 --- /dev/null +++ b/krb5-1-7/src/kim/test/main.c @@ -0,0 +1,78 @@ +/* + * $Header$ + * + * 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. + */ + +#include "test_kim_identity.h" +#include "test_kim_preferences.h" +#include "test_kim_selection_hints.h" + +int main (int argc, const char * argv[]) +{ + kim_test_state_t state = NULL; + + if (test_init (&state)) { + return 1; + } + + test_kim_identity_create_from_krb5_principal (state); + + test_kim_identity_create_from_string (state); + + test_kim_identity_create_from_components (state); + + test_kim_identity_copy (state); + + test_kim_identity_compare (state); + + test_kim_identity_get_display_string (state); + + test_kim_identity_get_realm (state); + + test_kim_identity_get_number_of_components (state); + + test_kim_identity_get_component_at_index (state); + + test_kim_identity_get_krb5_principal (state); + + test_kim_preferences_create (state); + + test_kim_preferences_copy (state); + + test_kim_preferences_set_options (state); + + test_kim_preferences_set_remember_options (state); + + test_kim_preferences_set_client_identity (state); + + test_kim_selection_hints_set_hint (state); + + test_kim_selection_hints_remember_identity (state); + + test_kim_preferences_add_favorite_identity (state); + + test_kim_preferences_remove_favorite_identity(state); + + return test_cleanup (state); +} diff --git a/krb5-1-7/src/kim/test/test_kim_common.c b/krb5-1-7/src/kim/test/test_kim_common.c new file mode 100644 index 000000000..802d41564 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_common.c @@ -0,0 +1,138 @@ +/* + * $Header$ + * + * 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. + */ + +#include + +const char *k_no_test_name = "No test name set"; + +/* ------------------------------------------------------------------------ */ + +int test_init (kim_test_state_t *out_state) +{ + kim_test_state_t state = NULL; + + printf ("Initializing tests... "); + + state = malloc (sizeof (*state)); + if (!state) { + printf ("out of memory.\n\n"); + return 1; + } + + state->test_name = k_no_test_name; + state->global_fail_count = 0; + state->test_fail_count = 0; + + *out_state = state; + + printf ("done.\n\n"); + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +int test_cleanup (kim_test_state_t io_state) +{ + int global_fail_count = io_state->global_fail_count; + + printf ("Exiting. %d total failures.", global_fail_count); + free (io_state); + + return global_fail_count; +} + +/* ------------------------------------------------------------------------ */ + +void start_test (kim_test_state_t in_state, + const char *in_test_name) +{ + in_state->test_name = in_test_name; + in_state->test_fail_count = 0; + + printf ("Testing %s...\n", in_state->test_name); +} + +/* ------------------------------------------------------------------------ */ + +void end_test (kim_test_state_t in_state) +{ + printf ("Finished testing %s. %d failures.\n\n", + in_state->test_name, in_state->test_fail_count); + + in_state->test_name = k_no_test_name; + in_state->global_fail_count += in_state->test_fail_count; + in_state->test_fail_count = 0; +} + +/* ------------------------------------------------------------------------ */ + +void fail_if_error (kim_test_state_t in_state, + const char *in_function, + kim_error in_err, + const char *in_format, + ...) +{ + if (in_err) { + va_list args; + kim_string message = NULL; + + kim_error err = kim_string_create_for_last_error (&message, in_err); + + printf ("\tFAILURE: "); + printf ("%s() got %d (%s) ", + in_function, in_err, !err ? message : "Unknown"); + + va_start (args, in_format); + vprintf (in_format, args); + va_end (args); + + printf ("\n"); + + in_state->test_fail_count++; + + kim_string_free (&message); + } +} + +/* ------------------------------------------------------------------------ */ + +void log_failure (kim_test_state_t in_state, + const char *in_format, + ...) +{ + va_list args; + + printf ("\tFAILURE: "); + + va_start (args, in_format); + vprintf (in_format, args); + va_end (args); + + printf ("\n"); + + in_state->test_fail_count++; +} diff --git a/krb5-1-7/src/kim/test/test_kim_common.h b/krb5-1-7/src/kim/test/test_kim_common.h new file mode 100644 index 000000000..e7ac3eb30 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_common.h @@ -0,0 +1,68 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef TEST_KIM_COMMON_H +#define TEST_KIM_COMMON_H + +#include +#include +#include +#include + +typedef struct kim_test_state_d { + const char *test_name; + int global_fail_count; + int test_fail_count; +} *kim_test_state_t; + +int test_init (kim_test_state_t *out_state); + +int test_cleanup (kim_test_state_t io_state); + +void start_test (kim_test_state_t in_state, + const char *in_test_name); + +void end_test (kim_test_state_t in_state); + +void fail_if_error (kim_test_state_t in_state, + const char *in_function, + kim_error in_err, + const char *in_format, + ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__ ((__format__ (__printf__, 4, 5))) +#endif +; + +void log_failure (kim_test_state_t in_state, + const char *in_format, + ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__ ((__format__ (__printf__, 2, 3))) +#endif +; + +#endif /* TEST_KIM_COMMON_H */ diff --git a/krb5-1-7/src/kim/test/test_kim_identity.c b/krb5-1-7/src/kim/test/test_kim_identity.c new file mode 100644 index 000000000..2f1ac089f --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_identity.c @@ -0,0 +1,595 @@ +/* + * $Header$ + * + * 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. + */ + +#include "test_kim_identity.h" + +typedef struct test_identity_d { + const char *string; + const char *display_string; + kim_boolean is_tgt_service; + const char *realm; + kim_count component_count; + const char *components[5]; +} test_identity; + + +test_identity test_identities[] = { + {"a@B", "a@B", 0, "B", 1, { "a", NULL, NULL, NULL, NULL } }, + {"user@EXAMPLE.COM", "user@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "user", NULL, NULL, NULL, NULL } }, + {"krbtgt@EXAMPLE.COM", "krbtgt@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "krbtgt", NULL, NULL, NULL, NULL } }, + {"krbtgt/EXAMPLE.COM@EXAMPLE.COM", "krbtgt/EXAMPLE.COM@EXAMPLE.COM", 1, "EXAMPLE.COM", 2, { "krbtgt", "EXAMPLE.COM", NULL, NULL, NULL } }, + {"krbtgt/OTHER.COM@EXAMPLE.COM", "krbtgt/OTHER.COM@EXAMPLE.COM", 1, "EXAMPLE.COM", 2, { "krbtgt", "OTHER.COM", NULL, NULL, NULL } }, + {"a space@EXAMPLE.COM", "a space@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "a space", NULL, NULL, NULL, NULL } }, + {"üñîçödé@EXAMPLE.COM", "üñîçödé@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "üñîçödé", NULL, NULL, NULL, NULL } }, + {"user.name@EXAMPLE.COM", "user.name@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "user.name", NULL, NULL, NULL, NULL } }, + {"user\\/instance@EXAMPLE.COM", "user/instance@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "user\/instance", NULL, NULL, NULL, NULL } }, + {"user\\@instance@EXAMPLE.COM", "user@instance@EXAMPLE.COM", 0, "EXAMPLE.COM", 1, { "user\@instance", NULL, NULL, NULL, NULL } }, + {"user/instance@EXAMPLE.COM", "user/instance@EXAMPLE.COM", 0, "EXAMPLE.COM", 2, { "user", "instance", NULL, NULL, NULL } }, + {"user/i1/i2@EXAMPLE.COM", "user/i1/i2@EXAMPLE.COM", 0, "EXAMPLE.COM", 3, { "user", "i1", "i2", NULL, NULL } }, + {"user/i1/i2/i3/i4@EXAMPLE.COM", "user/i1/i2/i3/i4@EXAMPLE.COM", 0, "EXAMPLE.COM", 5, { "user", "i1", "i2", "i3", "i4" } }, + {"an insanely long principal for testing icky hex key principals/an insanely long instance for testing icky hex key principals@AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES", + "an insanely long principal for testing icky hex key principals/an insanely long instance for testing icky hex key principals@AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES", + 0, "AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES", + 2, { "an insanely long principal for testing icky hex key principals", "an insanely long instance for testing icky hex key principals", NULL, NULL, NULL } }, + { NULL, NULL, 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } }, +}; + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_create_from_krb5_principal (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_create_from_krb5_principal"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + krb5_context context = NULL; + krb5_principal principal = NULL; + kim_identity identity = NULL; + kim_string string = NULL; + + printf ("."); + + err = krb5_init_context (&context); + fail_if_error (state, "krb5_init_context", err, + "while initializing context"); + + if (!err) { + err = krb5_parse_name (context, test_identities[i].string, &principal); + fail_if_error (state, "krb5_parse_name", err, + "while creating krb5_principal for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_create_from_krb5_principal (&identity, context, principal); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_string (identity, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for %s", + test_identities[i].string); + } + + if (!err && strcmp (string, test_identities[i].string)) { + log_failure (state, "Unexpected string (got '%s', expected '%s')", + string, test_identities[i].string); + } + + kim_string_free (&string); + kim_identity_free (&identity); + if (principal) { krb5_free_principal (context, principal); } + if (context ) { krb5_free_context (context); } + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_create_from_string (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_create_from_string"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_string string = NULL; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_string (identity, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for %s", + test_identities[i].string); + } + + if (!err && strcmp (string, test_identities[i].string)) { + log_failure (state, "Unexpected string (got '%s', expected '%s')", + string, test_identities[i].string); + } + + kim_string_free (&string); + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_create_from_components (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_create_from_components"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_string string = NULL; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_components (&identity, + test_identities[i].realm, + test_identities[i].components[0], + test_identities[i].components[1], + test_identities[i].components[2], + test_identities[i].components[3], + test_identities[i].components[4], + NULL); + fail_if_error (state, "kim_identity_create_from_components", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_string (identity, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for %s", + test_identities[i].string); + } + + if (!err && strcmp (string, test_identities[i].string)) { + log_failure (state, "Unexpected string (got '%s', expected '%s')", + string, test_identities[i].string); + } + + kim_string_free (&string); + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_copy (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_copy"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_identity identity_copy = NULL; + kim_string string = NULL; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_copy (&identity_copy, identity); + fail_if_error (state, "kim_identity_copy", err, + "while copying %s", test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_string (identity_copy, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for the copy of %s", + test_identities[i].string); + } + + if (!err && strcmp (string, test_identities[i].string)) { + log_failure (state, "Unexpected string (got '%s', expected '%s')", + string, test_identities[i].string); + } + + kim_string_free (&string); + kim_identity_free (&identity_copy); + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_compare (kim_test_state_t state) +{ + kim_count i, j = 0; + + start_test (state, "kim_identity_create_from_string"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + printf ("."); + + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + + for (j = 0; !err && test_identities[j].string; j++) { + kim_identity compare_to_identity = NULL; + kim_comparison comparison = 0; + + err = kim_identity_create_from_string (&compare_to_identity, test_identities[j].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[j].string); + + if (!err) { + err = kim_identity_compare (identity, compare_to_identity, &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s and %s", + test_identities[i].string, test_identities[j].string); + } + + if (!err) { + if (i == j && !kim_comparison_is_equal_to (comparison)) { + log_failure (state, "Expected %s and %s to be equal but kim_identity_compare returned %d", + test_identities[i].string, test_identities[j].string, comparison); + + } else if (i != j && kim_comparison_is_equal_to (comparison)) { + log_failure (state, "Expected %s and %s to be NOT equal but kim_identity_compare returned %d", + test_identities[i].string, test_identities[j].string, comparison); + } + } + + kim_identity_free (&compare_to_identity); + } + + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_get_display_string (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_get_display_string"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_string string = NULL; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_display_string (identity, &string); + fail_if_error (state, "kim_identity_get_display_string", err, + "while getting the display string for %s", + test_identities[i].string); + } + + if (!err && strcmp (string, test_identities[i].display_string)) { + log_failure (state, "Unexpected display string for %s (got '%s', expected '%s')", + test_identities[i].string, string, test_identities[i].display_string); + } + + kim_string_free (&string); + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_get_realm (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_get_realm"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_string realm = NULL; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_realm (identity, &realm); + fail_if_error (state, "kim_identity_get_realm", err, + "while getting the realm for %s", test_identities[i].string); + } + + if (!err && strcmp (realm, test_identities[i].realm)) { + log_failure (state, "Unexpected realm string (got '%s', expected '%s')", + realm, test_identities[i].realm); + } + + kim_string_free (&realm); + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_get_number_of_components (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_get_number_of_components"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_count count = 0; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_get_number_of_components (identity, &count); + fail_if_error (state, "kim_identity_get_number_of_components", err, + "while getting number of components of %s", + test_identities[i].string); + } + + if (!err && (count != test_identities[i].component_count)) { + log_failure (state, "Unexpected component count of %s (got %d, expected %d)", + test_identities[i].string, (int) count, (int) test_identities[i].component_count); + } + + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_get_component_at_index (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_get_component_at_index"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_count c = 0; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + for (c = 0; !err && c < test_identities[i].component_count; c++) { + kim_string component = NULL; + + err = kim_identity_get_component_at_index (identity, c, &component); + fail_if_error (state, "kim_identity_get_component_at_index", err, + "while getting component %d of %s", (int) c, + test_identities[i].string); + + if (!err && strcmp (component, test_identities[i].components[c])) { + log_failure (state, "Unexpected component %d of %s (got '%s', expected '%s')", + (int) c, test_identities[i].string, + component, test_identities[i].components[c]); + } + + kim_string_free (&component); + } + + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_identity_get_krb5_principal (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_get_krb5_principal"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + krb5_context context = NULL; + krb5_principal principal = NULL; + krb5_principal identity_principal = NULL; + kim_identity identity = NULL; + + printf ("."); + + err = krb5_init_context (&context); + fail_if_error (state, "krb5_init_context", err, + "while initializing context"); + + if (!err) { + err = krb5_parse_name (context, test_identities[i].string, &principal); + fail_if_error (state, "krb5_parse_name", err, + "while creating krb5_principal for %s", + test_identities[i].string); + } + + if (!err && !err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err && !err) { + err = kim_identity_get_krb5_principal (identity, context, &identity_principal); + fail_if_error (state, "kim_identity_get_krb5_principal", err, + "while getting the krb5_principal for %s", + test_identities[i].string); + } + + if (!err && !err) { + if (!krb5_principal_compare (context, principal, identity_principal)) { + log_failure (state, "Principal and identity principal for %s do not match", + test_identities[i].string); + } + } + + kim_identity_free (&identity); + if (identity_principal) { krb5_free_principal (context, identity_principal); } + if (principal ) { krb5_free_principal (context, principal); } + if (context ) { krb5_free_context (context); } + } + + printf ("\n"); + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ +/* +void test_kim_identity_is_tgt_service (kim_test_state_t state) +{ + kim_count i = 0; + + start_test (state, "kim_identity_is_tgt_service"); + + for (i = 0; test_identities[i].string; i++) { + kim_error err = KIM_NO_ERROR; + kim_identity_t identity = NULL; + kim_boolean_t is_tgt_service = 0; + + printf ("."); + + if (!err) { + err = kim_identity_create_from_string (&identity, test_identities[i].string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + test_identities[i].string); + } + + if (!err) { + err = kim_identity_is_tgt_service (identity, &is_tgt_service); + fail_if_error (state, "kim_identity_is_tgt_service", err, + "while determining if %s is a tgt service", + test_identities[i].string); + } + + if (!err && (is_tgt_service != test_identities[i].is_tgt_service)) { + log_failure (state, "Unexpected result from kim_identity_is_tgt_service for %s (got %d, expected %d)", + test_identities[i].string, is_tgt_service, test_identities[i].is_tgt_service); + } + + kim_identity_free (&identity); + } + + printf ("\n"); + + end_test (state); +} +*/ diff --git a/krb5-1-7/src/kim/test/test_kim_identity.h b/krb5-1-7/src/kim/test/test_kim_identity.h new file mode 100644 index 000000000..cb7b29055 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_identity.h @@ -0,0 +1,52 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef TEST_KIM_IDENTITY_H +#define TEST_KIM_IDENTITY_H + +#include "test_kim_common.h" + +void test_kim_identity_create_from_krb5_principal (kim_test_state_t state); + +void test_kim_identity_create_from_string (kim_test_state_t state); + +void test_kim_identity_create_from_components (kim_test_state_t state); + +void test_kim_identity_copy (kim_test_state_t state); + +void test_kim_identity_compare (kim_test_state_t state); + +void test_kim_identity_get_display_string (kim_test_state_t state); + +void test_kim_identity_get_realm (kim_test_state_t state); + +void test_kim_identity_get_number_of_components (kim_test_state_t state); + +void test_kim_identity_get_component_at_index (kim_test_state_t state); + +void test_kim_identity_get_krb5_principal (kim_test_state_t state); + +#endif /* TEST_KIM_IDENTITY_H */ diff --git a/krb5-1-7/src/kim/test/test_kim_preferences.c b/krb5-1-7/src/kim/test/test_kim_preferences.c new file mode 100644 index 000000000..2766ad4d1 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_preferences.c @@ -0,0 +1,918 @@ +/* + * $Header$ + * + * 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. + */ + +#include "test_kim_preferences.h" + +#define TEST_LIFETIME 7777 + +void print_favorites(kim_test_state_t state); +kim_boolean favorites_contains_identity(kim_test_state_t state, kim_identity identity); + +/* ------------------------------------------------------------------------ */ + +void print_favorites(kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_count count, j; + kim_string string; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &count); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities"); + printf("%qu favorites...\n", count); + } + + + for (j = 0; j < count; j++) { + kim_identity compare_identity = NULL; + kim_options compare_options = NULL; + err = kim_preferences_get_favorite_identity_at_index (prefs, j, + &compare_identity, + &compare_options); + fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, + "while getting favorite identity %d", (int) j); + + if (!err) + { + kim_identity_get_display_string(compare_identity, &string); + printf(" %2qu: %s\n", j, string); + } + + kim_identity_free (&compare_identity); + kim_options_free (&compare_options); + } + + kim_preferences_free (&prefs); +} + +/* ------------------------------------------------------------------------ */ + +kim_boolean favorites_contains_identity(kim_test_state_t state, kim_identity identity) +{ + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_count count, j; + kim_boolean found = 0; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &count); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities"); + } + + for (j = 0; j < count; j++) { + kim_identity compare_identity = NULL; + kim_options compare_options = NULL; + kim_comparison comparison = 0; + + err = kim_preferences_get_favorite_identity_at_index (prefs, j, + &compare_identity, + &compare_options); + fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, + "while getting favorite identity %d", (int) j); + + if (!err) { + kim_string display_string = NULL; + err = kim_identity_compare (identity, compare_identity, + &comparison); + if (err) { + kim_identity_get_display_string(identity, &display_string); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to favorite identity %d", + display_string, (int) j); + } + } + + if (!err && kim_comparison_is_equal_to (comparison)) { + found = 1; + } + + kim_identity_free (&compare_identity); + kim_options_free (&compare_options); + } + + kim_preferences_free (&prefs); + + return found; +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_create (kim_test_state_t state) +{ + + start_test (state, "kim_preferences_create"); + + { + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + kim_preferences_free (&prefs); + } + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_copy (kim_test_state_t state) +{ + + start_test (state, "test_kim_preferences_copy"); + + { + kim_error err = KIM_NO_ERROR; + kim_preferences prefs = NULL; + kim_preferences prefs_copy = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_copy (&prefs_copy, prefs); + fail_if_error (state, "kim_preferences_copy", err, + "while copying preferences"); + } + + kim_preferences_free (&prefs_copy); + kim_preferences_free (&prefs); + } + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_set_options (kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + + start_test (state, "kim_preferences_set_options"); + + if (!err) { + kim_preferences prefs = NULL; + kim_options options = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_options (prefs, &options); + fail_if_error (state, "kim_preferences_get_options", err, + "while getting old options"); + } + + if (!err) { + err = kim_options_set_lifetime (options, TEST_LIFETIME); + fail_if_error (state, "kim_options_set_lifetime", err, + "while setting the lifetime to %d", TEST_LIFETIME); + } + + if (!err) { + err = kim_preferences_set_options (prefs, options); + fail_if_error (state, "kim_preferences_set_options", err, + "while setting the new options"); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + kim_options_free (&options); + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + kim_options verify_options = NULL; + kim_lifetime lifetime = 0; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + + if (!err) { + err = kim_preferences_get_options (prefs, &verify_options); + fail_if_error (state, "kim_preferences_get_options", err, + "while getting options for verification"); + } + + if (!err) { + err = kim_options_get_lifetime (verify_options, &lifetime); + fail_if_error (state, "kim_options_get_data", err, + "while getting the custom data of the verify options"); + } + + if (!err && lifetime != TEST_LIFETIME) { + log_failure (state, "Unexpected lifetime in options (got %d, expected %d)", + (int) lifetime, TEST_LIFETIME); + } + + kim_options_free (&verify_options); + kim_preferences_free (&prefs); + } + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_set_remember_options (kim_test_state_t state) +{ + + kim_error err = KIM_NO_ERROR; + + start_test (state, "kim_preferences_set_remember_options"); + + if (!err) { + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_set_remember_options (prefs, TRUE); + fail_if_error (state, "kim_preferences_set_remember_options", err, + "while setting the preference to remember options"); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + kim_boolean remember_options = TRUE; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_remember_options (prefs, &remember_options); + fail_if_error (state, "kim_preferences_get_remember_options", err, + "while getting the preference to remember options"); + } + + if (!err && !remember_options) { + log_failure (state, "Unexpected remember options preference (got %d, expected TRUE)", + remember_options); + } + + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_set_remember_options (prefs, FALSE); + fail_if_error (state, "kim_preferences_set_remember_options", err, + "while setting the preference to remember options"); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + kim_boolean remember_options = FALSE; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_remember_options (prefs, &remember_options); + fail_if_error (state, "kim_preferences_get_remember_options", err, + "while getting the preference to remember options"); + } + + if (!err && remember_options) { + log_failure (state, "Unexpected remember options preference (got %d, expected 0)", + remember_options); + } + + kim_preferences_free (&prefs); + } + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_set_client_identity (kim_test_state_t state) +{ + + kim_error err = KIM_NO_ERROR; + kim_string test_string = "user@EXAMPLE.COM"; + kim_identity test_identity = KIM_IDENTITY_ANY; + kim_identity identity = KIM_IDENTITY_ANY; + kim_comparison comparison = 0; + + start_test (state, "kim_preferences_set_client_identity"); + + + if (!err) { + err = kim_identity_create_from_string (&test_identity, test_string); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", test_string); + } + + if (!err) { + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_set_client_identity (prefs, KIM_IDENTITY_ANY); + fail_if_error (state, "kim_preferences_set_client_identity", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_client_identity (prefs, &identity); + fail_if_error (state, "kim_preferences_get_client_identity", err, + "while getting the client identity preference"); + } + + if (!err && identity != KIM_IDENTITY_ANY) { + log_failure (state, "Unexpected client identity preference (got %p, expected %p)", + identity, KIM_IDENTITY_ANY); + kim_identity_free (&identity); + } + + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_set_client_identity (prefs, test_identity); + fail_if_error (state, "kim_preferences_set_client_identity", err, + "while setting the identity to %s", test_string); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the identity to KIM_IDENTITY_ANY"); + } + + kim_preferences_free (&prefs); + } + + + if (!err) { + kim_preferences prefs = NULL; + kim_string string = NULL; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_client_identity (prefs, &identity); + fail_if_error (state, "kim_preferences_get_client_identity", err, + "while getting the client identity preference"); + } + + if (!err && identity) { + err = kim_identity_get_string (identity, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for client identity preference"); + } + + if (!err) { + err = kim_identity_compare (identity, test_identity, &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to the identity preference %s", + test_string, string ? string : "NULL"); + } + + if (!err && !kim_comparison_is_equal_to (comparison)) { + log_failure (state, "Unexpected client identity preference (got %s, expected %s)", + string ? string : "NULL", test_string); + kim_identity_free (&identity); + } + + kim_string_free (&string); + kim_preferences_free (&prefs); + } + + kim_identity_free (&identity); + kim_identity_free (&test_identity); + + end_test (state); +} + + +struct favorite_identity { + kim_string identity; + kim_lifetime lifetime; + kim_lifetime renewal_lifetime; +}; + +struct favorite_identity fids[] = { +{ "bob@EXAMPLE.COM", 7777, 8888 }, +{ "alice@UNIVERSITY.EDU", 12345, 54321 }, +{ "bob@COMPANY.COM", 5555, 6666 }, +{ "alice/admin@EXAMPLE.COM", 2222, 3333 }, +{ NULL, 0, 0 } +}; + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_add_favorite_identity (kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + + start_test (state, "kim_preferences_add_favorite_identity"); + + if (!err) { + kim_preferences prefs = NULL; + kim_options options = NULL; + kim_count i; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_remove_all_favorite_identities (prefs); + fail_if_error (state, "kim_preferences_remove_all_favorite_identities", err, + "while removing all favorite identities"); + } + + if (!err) { + err = kim_options_create (&options); + fail_if_error (state, "kim_options_create", err, + "while creating options"); + } + + for (i = 0; !err && fids[i].identity; i++) { + kim_identity identity = NULL; + + err = kim_identity_create_from_string (&identity, fids[i].identity); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + fids[i].identity); + + if (!err) { + err = kim_options_set_lifetime (options, fids[i].lifetime); + fail_if_error (state, "kim_options_set_lifetime", err, + "while setting the lifetime to %d", + (int) fids[i].lifetime); + } + + if (!err) { + err = kim_options_set_renewal_lifetime (options, fids[i].renewal_lifetime); + fail_if_error (state, "kim_options_set_renewal_lifetime", err, + "while setting the renewal lifetime to %d", + (int) fids[i].renewal_lifetime); + } + + if (!err) { + err = kim_preferences_add_favorite_identity (prefs, identity, options); + fail_if_error (state, "kim_preferences_add_favorite_identity", err, + "while adding %s to the favorite identities", + fids[i].identity); + } + + kim_identity_free (&identity); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the favorite identities"); + } + + kim_options_free (&options); + kim_preferences_free (&prefs); + } + + if (!err) { + kim_preferences prefs = NULL; + kim_count count, i; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &count); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities"); + } + + + for (i = 0; !err && fids[i].identity; i++) { + kim_identity identity = NULL; + kim_count j; + kim_boolean found = 0; + + err = kim_identity_create_from_string (&identity, fids[i].identity); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + fids[i].identity); + + for (j = 0; j < count; j++) { + kim_identity compare_identity = NULL; + kim_options compare_options = NULL; + kim_comparison comparison; + + err = kim_preferences_get_favorite_identity_at_index (prefs, j, + &compare_identity, + &compare_options); + fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, + "while getting favorite identity %d", (int) j); + + if (!err) { + err = kim_identity_compare (identity, compare_identity, + &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to favorite identity %d", + fids[i].identity, (int) i); + } + + if (!err && kim_comparison_is_equal_to (comparison)) { + kim_lifetime compare_lifetime; + kim_lifetime compare_renewal_lifetime; + + found = 1; + + err = kim_options_get_lifetime (compare_options, &compare_lifetime); + fail_if_error (state, "kim_options_get_lifetime", err, + "while getting the lifetime for %s", + fids[i].identity); + + if (!err && fids[i].lifetime != compare_lifetime) { + log_failure (state, "Unexpected lifetime for %s (got %d, expected %d)", + fids[i].identity, (int) compare_lifetime, + (int) fids[i].lifetime); + } + + if (!err) { + err = kim_options_get_renewal_lifetime (compare_options, + &compare_renewal_lifetime); + fail_if_error (state, "kim_options_get_renewal_lifetime", err, + "while getting the lifetime for %s", + fids[i].identity); + } + + if (!err && fids[i].renewal_lifetime != compare_renewal_lifetime) { + log_failure (state, "Unexpected renewal lifetime for %s (got %d, expected %d)", + fids[i].identity, + (int) compare_renewal_lifetime, + (int) fids[i].renewal_lifetime); + } + } + + kim_identity_free (&compare_identity); + kim_options_free (&compare_options); + } + + if (!err && !found) { + log_failure (state, "Favorite identity %s not found in favorite identities list", + fids[i].identity); + } + + kim_identity_free (&identity); + } + + if (!err && i != count) { + log_failure (state, "Unexpected number of favorite identities (got %d, expected %d)", + (int) count, (int) i); + } + + kim_preferences_free (&prefs); + } + + end_test (state); +} + +/* ------------------------------------------------------------------------ */ + +void test_kim_preferences_remove_favorite_identity (kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + + start_test (state, "kim_preferences_remove_favorite_identity"); + /* + * 1. Remove all favorites to start with a clean slate + * 2. Add some favorites + * 3. Verify added favorites + * 4. Remove those favorites one by one, checking each time to make sure they were removed + */ + + // Remove old and add new + if (!err) { + kim_preferences prefs = NULL; + kim_options options = NULL; + kim_count i; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_remove_all_favorite_identities (prefs); + fail_if_error (state, "kim_preferences_remove_all_favorite_identities", err, + "while removing all favorite identities"); + } + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &i); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities after clearing"); + } + + if (!err) { + err = kim_options_create (&options); + fail_if_error (state, "kim_options_create", err, + "while creating options"); + } + + for (i = 0; !err && fids[i].identity; i++) { + kim_identity identity = NULL; + + err = kim_identity_create_from_string (&identity, fids[i].identity); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + fids[i].identity); + + if (!err) { + err = kim_options_set_lifetime (options, fids[i].lifetime); + fail_if_error (state, "kim_options_set_lifetime", err, + "while setting the lifetime to %d", + (int) fids[i].lifetime); + } + + if (!err) { + err = kim_options_set_renewal_lifetime (options, fids[i].renewal_lifetime); + fail_if_error (state, "kim_options_set_renewal_lifetime", err, + "while setting the renewal lifetime to %d", + (int) fids[i].renewal_lifetime); + } + + if (!err) { + err = kim_preferences_add_favorite_identity (prefs, identity, options); + fail_if_error (state, "kim_preferences_add_favorite_identity", err, + "while adding %s to the favorite identities", + fids[i].identity); + } + + kim_identity_free (&identity); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while setting the favorite identities"); + } + + kim_options_free (&options); + kim_preferences_free (&prefs); + } + + // Verify add + if (!err) { + kim_preferences prefs = NULL; + kim_count count, i; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &count); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities"); + } + + + for (i = 0; !err && fids[i].identity; i++) { + kim_identity identity = NULL; + kim_count j; + kim_boolean found = 0; + + err = kim_identity_create_from_string (&identity, fids[i].identity); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating the identity for %s", + fids[i].identity); + + for (j = 0; j < count; j++) { + kim_identity compare_identity = NULL; + kim_options compare_options = NULL; + kim_comparison comparison; + + err = kim_preferences_get_favorite_identity_at_index (prefs, j, + &compare_identity, + &compare_options); + fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, + "while getting favorite identity %d", (int) j); + + if (!err) { + err = kim_identity_compare (identity, compare_identity, + &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to favorite identity %d", + fids[i].identity, (int) i); + } + + if (!err && kim_comparison_is_equal_to (comparison)) { + kim_lifetime compare_lifetime; + kim_lifetime compare_renewal_lifetime; + + found = 1; + + err = kim_options_get_lifetime (compare_options, &compare_lifetime); + fail_if_error (state, "kim_options_get_lifetime", err, + "while getting the lifetime for %s", + fids[i].identity); + + if (!err && fids[i].lifetime != compare_lifetime) { + log_failure (state, "Unexpected lifetime for %s (got %d, expected %d)", + fids[i].identity, (int) compare_lifetime, + (int) fids[i].lifetime); + } + + if (!err) { + err = kim_options_get_renewal_lifetime (compare_options, + &compare_renewal_lifetime); + fail_if_error (state, "kim_options_get_renewal_lifetime", err, + "while getting the lifetime for %s", + fids[i].identity); + } + + if (!err && fids[i].renewal_lifetime != compare_renewal_lifetime) { + log_failure (state, "Unexpected renewal lifetime for %s (got %d, expected %d)", + fids[i].identity, + (int) compare_renewal_lifetime, + (int) fids[i].renewal_lifetime); + } + } + + kim_identity_free (&compare_identity); + kim_options_free (&compare_options); + } + + if (!err && !found) { + log_failure (state, "Favorite identity %s not found in favorite identities list", + fids[i].identity); + } + + kim_identity_free (&identity); + } + + if (!err && i != count) { + log_failure (state, "Unexpected number of favorite identities (got %d, expected %d)", + (int) count, (int) i); + } + + kim_preferences_free (&prefs); + } + + // Remove one by one + if (!err) { + kim_preferences prefs = NULL; + kim_count count, j; + + err = kim_preferences_create (&prefs); + fail_if_error (state, "kim_preferences_create", err, + "while creating preferences"); + + if (!err) { + err = kim_preferences_get_number_of_favorite_identities (prefs, &count); + fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, + "while getting number of favorite identities"); + } + + for (j = 0; j < count; j++) { + kim_identity compare_identity = NULL; + kim_options compare_options = NULL; + kim_string string = NULL; + + err = kim_preferences_get_favorite_identity_at_index (prefs, 0, + &compare_identity, + &compare_options); + fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, + "while getting favorite identity %d", (int) j); + + if (!err) { + err = kim_identity_get_display_string(compare_identity, &string); + fail_if_error (state, "kim_identity_get_display_string", err, + "while getting the display string for identity %d", (int) j); + } + + if (!err) { + err = kim_preferences_remove_favorite_identity(prefs, compare_identity); + fail_if_error (state, "kim_preferences_remove_favorite_identity", err, + "while removing favorite identity %d \"%s\"", (int) j, string); + } + + if (!err) { + err = kim_preferences_synchronize (prefs); + fail_if_error (state, "kim_preferences_synchronize", err, + "while removing favorite %qu: %s", j, string); + } + + if (!err && favorites_contains_identity(state, compare_identity)) { + kim_string display_string = NULL; + kim_identity_get_display_string(compare_identity, &display_string); + log_failure (state, "Favorite identities still contains %s after removal", + display_string); + } + + kim_string_free (&string); + kim_identity_free (&compare_identity); + kim_options_free (&compare_options); + } + + kim_preferences_free (&prefs); + } + + end_test (state); +} diff --git a/krb5-1-7/src/kim/test/test_kim_preferences.h b/krb5-1-7/src/kim/test/test_kim_preferences.h new file mode 100644 index 000000000..d097d7eb1 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_preferences.h @@ -0,0 +1,46 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef TEST_KIM_PREFERENCES_H +#define TEST_KIM_PREFERENCES_H + +#include "test_kim_common.h" + +void test_kim_preferences_create (kim_test_state_t state); + +void test_kim_preferences_copy (kim_test_state_t state); + +void test_kim_preferences_set_options (kim_test_state_t state); + +void test_kim_preferences_set_remember_options (kim_test_state_t state); + +void test_kim_preferences_set_client_identity (kim_test_state_t state); + +void test_kim_preferences_add_favorite_identity (kim_test_state_t state); + +void test_kim_preferences_remove_favorite_identity (kim_test_state_t state); + +#endif /* TEST_KIM_PREFERENCES_H */ diff --git a/krb5-1-7/src/kim/test/test_kim_selection_hints.c b/krb5-1-7/src/kim/test/test_kim_selection_hints.c new file mode 100644 index 000000000..2a24a610e --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_selection_hints.c @@ -0,0 +1,178 @@ +/* + * $Header$ + * + * 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. + */ + +#include "test_kim_selection_hints.h" + +#define KSH_TEST_ID "edu.mit.Kerberos.test_kim" + +#define KSH_IDENTITY "jdoe@USERS.EXAMPLE.COM" + +typedef struct test_selection_hint_d { + kim_string key; + kim_string hint; +} test_selection_hint; + +test_selection_hint test_hints[] = { + { kim_hint_key_service_identity, "service/server.example.com@EXAMPLE.COM" }, + { kim_hint_key_service, "service" }, + { kim_hint_key_server, "server.example.com" }, + { kim_hint_key_service_realm, "EXAMPLE.COM" }, + { kim_hint_key_user, "jdoe" }, + { kim_hint_key_client_realm, "USERS.EXAMPLE.COM" }, + { NULL, NULL } +}; + +/* ------------------------------------------------------------------------ */ + +void test_kim_selection_hints_set_hint (kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + kim_count i = 0; + + start_test (state, "test_kim_selection_hints_set_hint"); + + for (i = 0; !err && test_hints[i].key; i++) { + kim_selection_hints hints = NULL; + kim_string string = NULL; + kim_comparison comparison = 0; + + printf ("."); + + err = kim_selection_hints_create (&hints, KSH_TEST_ID); + fail_if_error (state, "kim_selection_hints_create", err, + "while creating selection hints for %s", KSH_TEST_ID); + + if (!err) { + err = kim_selection_hints_set_hint (hints, test_hints[i].key, test_hints[i].hint); + fail_if_error (state, "kim_selection_hints_set_hint", + err, "while setting hint %s to %s", + test_hints[i].key, test_hints[i].hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (hints, test_hints[i].key, &string); + fail_if_error (state, "kim_selection_hints_get_hint", + err, "while getting hint %s", test_hints[i].key); + } + + if (!err) { + err = kim_string_compare (test_hints[i].hint, string, &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to %s (hint %s)", + test_hints[i].hint, + string ? string : "NULL", test_hints[i].key); + } + + if (!err && !kim_comparison_is_equal_to (comparison)) { + log_failure (state, "Unexpected hint %s (got %s, expected %s)", + test_hints[i].key, + string ? string : "NULL", + test_hints[i].hint); + } + + kim_string_free (&string); + kim_selection_hints_free (&hints); + } + + end_test (state); +} + + + +/* ------------------------------------------------------------------------ */ + +void test_kim_selection_hints_remember_identity (kim_test_state_t state) +{ + kim_error err = KIM_NO_ERROR; + kim_selection_hints hints = NULL; + kim_count i = 0; + kim_identity client_identity = NULL; + kim_string string = NULL; + kim_identity identity = KIM_IDENTITY_ANY; + kim_comparison comparison = 0; + + start_test (state, "kim_selection_hints_remember_identity"); + + if (!err) { + err = kim_selection_hints_create (&hints, KSH_TEST_ID); + fail_if_error (state, "kim_selection_hints_create", err, + "while creating selection hints for %s", KSH_TEST_ID); + } + + for (i = 0; !err && test_hints[i].key; i++) { + err = kim_selection_hints_set_hint (hints, test_hints[i].key, test_hints[i].hint); + fail_if_error (state, "kim_selection_hints_set_hint", + err, "while setting hint %s to %s", + test_hints[i].key, test_hints[i].hint); + } + + if (!err) { + err = kim_identity_create_from_string (&client_identity, + KSH_IDENTITY); + fail_if_error (state, "kim_identity_create_from_string", err, + "while creating an identity for %s", + KSH_IDENTITY); + } + + if (!err) { + err = kim_selection_hints_remember_identity (hints, client_identity); + fail_if_error (state, "kim_selection_hints_remember_identity", + err, "while remembering identity %s", + KSH_IDENTITY); + } + + if (!err) { + err = kim_selection_hints_get_identity (hints, &identity); + fail_if_error (state, "kim_selection_hints_get_identity", + err, "while checking if identity is %s", + KSH_IDENTITY); + } + + if (!err && identity) { + err = kim_identity_get_string (identity, &string); + fail_if_error (state, "kim_identity_get_string", err, + "while getting the string for the client identity hint"); + } + + if (!err) { + err = kim_identity_compare (client_identity, identity, &comparison); + fail_if_error (state, "kim_identity_compare", err, + "while comparing %s to the identity hint %s", + KSH_IDENTITY, string ? string : "NULL"); + } + + if (!err && !kim_comparison_is_equal_to (comparison)) { + log_failure (state, "Unexpected client identity hint (got %s, expected %s)", + string ? string : "NULL", KSH_IDENTITY); + } + + kim_string_free (&string); + kim_identity_free (&identity); + kim_identity_free (&client_identity); + kim_selection_hints_free (&hints); + + end_test (state); +} diff --git a/krb5-1-7/src/kim/test/test_kim_selection_hints.h b/krb5-1-7/src/kim/test/test_kim_selection_hints.h new file mode 100644 index 000000000..1bc0ce0e0 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kim_selection_hints.h @@ -0,0 +1,36 @@ +/* + * $Header$ + * + * 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. + */ + +#ifndef TEST_KIM_SELECTION_HINTS_H +#define TEST_KIM_SELECTION_HINTS_H + +#include "test_kim_common.h" + +void test_kim_selection_hints_set_hint (kim_test_state_t state); + +void test_kim_selection_hints_remember_identity (kim_test_state_t state); + +#endif /* TEST_KIM_SELECTION_HINTS_H */ diff --git a/krb5-1-7/src/kim/test/test_kll.c b/krb5-1-7/src/kim/test/test_kll.c new file mode 100644 index 000000000..d1773ae30 --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kll.c @@ -0,0 +1,556 @@ +#include +#include +#include +#include +#include + +/* Prototypes */ +void Initialize(void); +void TestErrorHandling (void); +void TestHighLevelAPI (void); +void TestKLPrincipal (void); +void TestKerberosRealms (void); +void TestLoginOptions (void); +char* TimeToString (char* timeString, long t); +void TestApplicationOptions (void); +void MyKerberosLoginIdleCallback ( + KLRefCon inAppData); + +int main(void) +{ + KLTime t; + KLStatus err; + KLPrincipal principal; + + /* force use of UI */ + fclose (stdin); + + err = KLCreatePrincipalFromTriplet ("nobody", "", "TEST-KERBEROS-1.3.1", &principal); + printf ("KLCreatePrincipalFromTriplet(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + err = KLChangePassword (principal); + printf ("KLChangePassword() (err = %d)\n", err); + KLDisposePrincipal (principal); + } + + err = KLLastChangedTime(&t); + printf ("KLLastChangedTime returned %d (err = %d)\n", t, err); + + TestKLPrincipal (); + TestLoginOptions (); + TestApplicationOptions (); + TestErrorHandling (); + TestKerberosRealms (); + TestHighLevelAPI (); + + err = KLLastChangedTime(&t); + printf ("KLLastChangedTime returned %d (err = %d)\n", t, err); + + return 0; +} + +void TestErrorHandling (void) +{ + long err; + char* errorString; + + err = KLGetErrorString (KRB5KRB_AP_ERR_BAD_INTEGRITY, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klCredentialsBadAddressErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klCacheDoesNotExistErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klPasswordMismatchErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klInsecurePasswordErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klPasswordChangeFailedErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klCantContactServerErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } + + err = KLGetErrorString (klCantDisplayUIErr, &errorString); + printf ("KLGetErrorString() returned %s (err = %ld)\n", errorString, err); + if (!err) { KLDisposeString (errorString); } +} + +void TestHighLevelAPI (void) +{ + KLStatus err; + KLPrincipal inPrincipal, outPrincipal, outPrincipal2; + char *outCredCacheName, *outCredCacheName2; + KLTime expirationTime; + char* principalString; + char timeString[256]; + KLBoolean valid; + + err = KLCreatePrincipalFromTriplet ("grail", "", "TESTV5-KERBEROS-1.3.1", &inPrincipal); + printf ("KLCreatePrincipalFromTriplet(grail@TESTV5-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + err = KLAcquireNewInitialTicketsWithPassword (inPrincipal, NULL, "liarg", &outCredCacheName); + if (err != klNoErr) { + printf ("KLAcquireNewInitialTicketsWithPassword() returned err = %d\n", err); + } else { + printf ("KLAcquireNewInitialTicketsWithPassword() returned '%s'\n", outCredCacheName); + KLDisposeString (outCredCacheName); + } + KLDisposePrincipal (inPrincipal); + } + + err = KLCreatePrincipalFromTriplet ("nobody", "", "TEST-KERBEROS-1.3.1", &inPrincipal); + printf ("KLCreatePrincipalFromTriplet(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + err = KLAcquireNewInitialTicketsWithPassword (inPrincipal, NULL, "ydobon", &outCredCacheName); + if (err != klNoErr) { + printf ("KLAcquireNewInitialTicketsWithPassword() returned err = %d\n", err); + } else { + printf ("KLAcquireNewInitialTicketsWithPassword() returned '%s'\n", outCredCacheName); + KLDisposeString (outCredCacheName); + } + KLDisposePrincipal (inPrincipal); + } + + err = KLAcquireNewInitialTickets (NULL, NULL, &inPrincipal, &outCredCacheName); + printf ("KLAcquireNewInitialTickets() (err = %d)\n", err); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + err = KLAcquireInitialTickets (inPrincipal, NULL, &outPrincipal, &outCredCacheName); + printf ("KLAcquireInitialTickets() (err = %d)\n", err); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + KLDisposePrincipal (inPrincipal); + } + + err = KLSetDefaultLoginOption (loginOption_LoginName, "testname", 3); + printf ("KLSetDefaultLoginOption(loginOption_LoginName) to testname (err = %d)\n", err); + if (err == klNoErr) { + err = KLSetDefaultLoginOption (loginOption_LoginInstance, "testinstance", 6); + printf ("KLSetDefaultLoginOption(loginOption_LoginInstance) to testinstance (err = %d)\n", err); + } + + err = KLAcquireNewInitialTickets (NULL, NULL, &inPrincipal, &outCredCacheName); + printf ("KLAcquireNewInitialTickets() (err = %d)\n", err); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + KLDisposePrincipal (inPrincipal); + } + + // Principal == NULL + while (KLAcquireNewInitialTickets (NULL, NULL, &outPrincipal, &outCredCacheName) == klNoErr) { + err = KLTicketExpirationTime (outPrincipal, kerberosVersion_All, &expirationTime); + err = KLCacheHasValidTickets (outPrincipal, kerberosVersion_All, &valid, &outPrincipal2, &outCredCacheName2); + if (err == klNoErr) { + err = KLGetStringFromPrincipal (outPrincipal2, kerberosVersion_V4, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal returned string '%s'\n", principalString); + KLDisposeString (principalString); + } + KLDisposePrincipal (outPrincipal2); + KLDisposeString (outCredCacheName2); + err = KLCacheHasValidTickets (outPrincipal, kerberosVersion_All, &valid, NULL, NULL); + if (err != klNoErr) { + printf ("KLCacheHasValidTickets returned error = %d\n", err); + } + } + err = KLCacheHasValidTickets (outPrincipal, kerberosVersion_All, &valid, NULL, NULL); + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + + err = KLAcquireNewInitialTickets (NULL, NULL, &outPrincipal, &outCredCacheName); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + + + err = KLCreatePrincipalFromTriplet ("nobody", "", "TEST-KERBEROS-1.3.1", &inPrincipal); + printf ("KLCreatePrincipalFromTriplet(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + err = KLAcquireNewInitialTickets (inPrincipal, NULL, &outPrincipal, &outCredCacheName); + printf ("KLAcquireNewInitialTickets(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + err = KLDestroyTickets (inPrincipal); + + KLDisposePrincipal (inPrincipal); + } + + err = KLCreatePrincipalFromTriplet ("nobody", "", "TEST-KERBEROS-1.3.1", &inPrincipal); + printf ("KLCreatePrincipalFromTriplet(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + err = KLAcquireInitialTickets (inPrincipal, NULL, &outPrincipal, &outCredCacheName); + printf ("KLAcquireInitialTickets(nobody@TEST-KERBEROS-1.3.1) (err = %d)\n", err); + if (err == klNoErr) { + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + + err = KLAcquireNewInitialTickets (inPrincipal, NULL, &outPrincipal, &outCredCacheName); + if (err == klNoErr) { + err = KLGetStringFromPrincipal (outPrincipal, kerberosVersion_V5, &principalString); + if (err == klNoErr) { + err = KLTicketExpirationTime (outPrincipal, kerberosVersion_All, &expirationTime); + printf ("Tickets for principal '%s' expire on %s\n", + principalString, TimeToString(timeString, expirationTime)); + + KLDisposeString (principalString); + } + KLDisposeString (outCredCacheName); + KLDisposePrincipal (outPrincipal); + } + + err = KLChangePassword (inPrincipal); + printf ("KLChangePassword() (err = %d)\n", err); + + err = KLDestroyTickets (inPrincipal); + printf ("KLDestroyTickets() (err = %d)\n", err); + + KLDisposePrincipal (inPrincipal); + } + +} + + +void TestKLPrincipal (void) +{ + KLStatus err = klNoErr; + KLPrincipal extraLongPrincipal = NULL; + KLPrincipal principal = NULL; + KLPrincipal adminPrincipal = NULL; + KLPrincipal adminPrincipalV4 = NULL; + KLPrincipal adminPrincipalV5 = NULL; + char *principalString = NULL; + char *user = NULL; + char *instance = NULL; + char *realm = NULL; + + printf ("Entering TestKLPrincipal()\n"); + printf ("----------------------------------------------------------------\n"); + + err = KLCreatePrincipalFromString ("thisprincipalnameislongerthanissupportedbyKerberos4@TEST-KERBEROS-1.3.1", + kerberosVersion_V5, &extraLongPrincipal); + printf ("KLCreatePrincipalFromString " + "('thisprincipalnameislongerthanissupportedbyKerberos4@TEST-KERBEROS-1.3.1') " + "(err = %s)\n", error_message(err)); + + printf ("----------------------------------------------------------------\n"); + + err = KLCreatePrincipalFromTriplet ("nobody", "", "TEST-KERBEROS-1.3.1", &principal); + printf ("KLCreatePrincipalFromTriplet ('nobody' '' 'TEST-KERBEROS-1.3.1') (err = %s)\n", + error_message(err)); + + if (err == klNoErr) { + err = KLGetStringFromPrincipal (principal, kerberosVersion_V5, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody@TEST-KERBEROS-1.3.1, v5) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody@TEST-KERBEROS-1.3.1, v5) returned (err = %s)\n", error_message(err)); + } + + err = KLGetStringFromPrincipal (principal, kerberosVersion_V4, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody@TEST-KERBEROS-1.3.1, v4) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody@TEST-KERBEROS-1.3.1, v4) returned (err = %s)\n", error_message(err)); + } + + err = KLGetTripletFromPrincipal (principal, &user, &instance, &realm); + if (err == klNoErr) { + printf ("KLGetTripletFromPrincipal (nobody@TEST-KERBEROS-1.3.1) returned triplet %s' '%s' '%s'\n", + user, instance, realm); + KLDisposeString (user); + KLDisposeString (instance); + KLDisposeString (realm); + } else { + printf ("KLGetTripletFromPrincipal(nobody@TEST-KERBEROS-1.3.1) returned (err = %s)\n", error_message(err)); + } + } + + printf ("----------------------------------------------------------------\n"); + + err = KLCreatePrincipalFromTriplet ("nobody", "admin", "TEST-KERBEROS-1.3.1", &adminPrincipal); + printf ("KLCreatePrincipalFromTriplet ('nobody' 'admin' 'TEST-KERBEROS-1.3.1') (err = %d)\n", err); + + if (err == klNoErr) { + err = KLGetStringFromPrincipal (adminPrincipal, kerberosVersion_V5, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody/admin@TEST-KERBEROS-1.3.1, v5) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody/admin@TEST-KERBEROS-1.3.1, v5) returned (err = %d)\n", err); + } + + err = KLGetStringFromPrincipal (adminPrincipal, kerberosVersion_V4, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody/admin@TEST-KERBEROS-1.3.1, v4) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody/admin@TEST-KERBEROS-1.3.1, v4) returned (err = %d)\n", err); + } + + err = KLGetTripletFromPrincipal (adminPrincipal, &user, &instance, &realm); + if (err == klNoErr) { + printf ("KLGetTripletFromPrincipal (nobody/admin@TEST-KERBEROS-1.3.1) returned triplet %s' '%s' '%s'\n", + user, instance, realm); + KLDisposeString (user); + KLDisposeString (instance); + KLDisposeString (realm); + } else { + printf ("KLGetTripletFromPrincipal(lxs/admin@TEST-KERBEROS-1.3.1) returned (err = %d)\n", err); + } + } + + printf ("----------------------------------------------------------------\n"); + + err = KLCreatePrincipalFromString ("nobody/root@TEST-KERBEROS-1.3.1", kerberosVersion_V5, &adminPrincipalV5); + printf ("KLCreatePrincipalFromString ('nobody/root@TEST-KERBEROS-1.3.1', v5) (err = %d)\n", err); + if (err == klNoErr) { + err = KLGetStringFromPrincipal (adminPrincipalV5, kerberosVersion_V5, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody/root@TEST-KERBEROS-1.3.1, v5) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody/root@TEST-KERBEROS-1.3.1, v5) returned (err = %d)\n", err); + } + + err = KLGetStringFromPrincipal (adminPrincipalV5, kerberosVersion_V4, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody/admin@TEST-KERBEROS-1.3.1, v4) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody/admin@TEST-KERBEROS-1.3.1, v4) returned (err = %d)\n", err); + } + + err = KLGetTripletFromPrincipal (adminPrincipalV5, &user, &instance, &realm); + if (err == klNoErr) { + printf ("KLGetTripletFromPrincipal (nobody/admin@TEST-KERBEROS-1.3.1) returned triplet %s' '%s' '%s'\n", + user, instance, realm); + KLDisposeString (user); + KLDisposeString (instance); + KLDisposeString (realm); + } else { + printf ("KLGetTripletFromPrincipal(nobody/admin@TEST-KERBEROS-1.3.1) returned (err = %d)\n", err); + } + } + + printf ("----------------------------------------------------------------\n"); + + err = KLCreatePrincipalFromString ("nobody.admin@TEST-KERBEROS-1.3.1", kerberosVersion_V4, &adminPrincipalV4); + printf ("KLCreatePrincipalFromString ('nobody.admin@TEST-KERBEROS-1.3.1') (err = %d)\n", err); + if (err == klNoErr) { + err = KLGetStringFromPrincipal (adminPrincipalV4, kerberosVersion_V5, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody.admin@TEST-KERBEROS-1.3.1, v5) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody.admin@TEST-KERBEROS-1.3.1, v5) returned (err = %d)\n", err); + } + + err = KLGetStringFromPrincipal (adminPrincipalV4, kerberosVersion_V4, &principalString); + if (err == klNoErr) { + printf ("KLGetStringFromPrincipal (nobody.admin@TEST-KERBEROS-1.3.1, v4) returned string '%s'\n", principalString); + KLDisposeString (principalString); + } else { + printf ("KLGetStringFromPrincipal(nobody.admin@TEST-KERBEROS-1.3.1, v4) returned (err = %d)\n", err); + } + + err = KLGetTripletFromPrincipal (adminPrincipalV4, &user, &instance, &realm); + if (err == klNoErr) { + printf ("KLGetTripletFromPrincipal (nobody.admin@TEST-KERBEROS-1.3.1) returned triplet %s' '%s' '%s'\n", + user, instance, realm); + KLDisposeString (user); + KLDisposeString (instance); + KLDisposeString (realm); + } else { + printf ("KLGetTripletFromPrincipal(nobody.admin@TEST-KERBEROS-1.3.1) returned (err = %d)\n", err); + } + } + + printf ("----------------------------------------------------------------\n"); + + if (adminPrincipalV4 != NULL && adminPrincipalV5 != NULL) { + KLBoolean equivalent; + + err = KLComparePrincipal (adminPrincipalV5, adminPrincipalV4, &equivalent); + if (err == klNoErr) { + printf ("KLComparePrincipal %s comparing nobody/admin@TEST-KERBEROS-1.3.1 and nobody.admin@TEST-KERBEROS-1.3.1\n", + equivalent ? "passed" : "FAILED"); + } else { + printf ("KLComparePrincipal returned (err = %d)\n", err); + } + } + + if (principal != NULL && adminPrincipalV5 != NULL) { + KLBoolean equivalent; + + err = KLComparePrincipal (principal, adminPrincipalV4, &equivalent); + if (err == klNoErr) { + printf ("KLComparePrincipal %s comparing nobody@TEST-KERBEROS-1.3.1 and nobody.admin@TEST-KERBEROS-1.3.1\n", + equivalent ? "FAILED" : "passed"); + } else { + printf ("KLComparePrincipal returned (err = %d)\n", err); + } + } + + if (principal != NULL && adminPrincipalV5 != NULL) { + KLBoolean equivalent; + + err = KLComparePrincipal (principal, adminPrincipalV5, &equivalent); + if (err == klNoErr) { + printf ("KLComparePrincipal %s comparing nobody@TEST-KERBEROS-1.3.1 and nobody/admin@TEST-KERBEROS-1.3.1\n", + equivalent ? "FAILED" : "passed"); + } else { + printf ("KLComparePrincipal returned (err = %d)\n", err); + } + } + + if (adminPrincipal != NULL && adminPrincipalV5 != NULL) { + KLBoolean equivalent; + + err = KLComparePrincipal (adminPrincipalV5, principal, &equivalent); + if (err == klNoErr) { + printf ("KLComparePrincipal %s comparing nobody/admin@TEST-KERBEROS-1.3.1 and nobody@TEST-KERBEROS-1.3.1\n", + equivalent ? "FAILED" : "passed"); + } else { + printf ("KLComparePrincipal returned (err = %d)\n", err); + } + } + + printf ("----------------------------------------------------------------\n\n"); + + if (extraLongPrincipal != NULL) KLDisposePrincipal (extraLongPrincipal); + if (adminPrincipalV5 != NULL) KLDisposePrincipal (adminPrincipalV5); + if (adminPrincipalV4 != NULL) KLDisposePrincipal (adminPrincipalV4); + if (adminPrincipal != NULL) KLDisposePrincipal (adminPrincipal); + if (principal != NULL) KLDisposePrincipal (principal); +} + + +void TestApplicationOptions (void) +{ + KLSetIdleCallback (MyKerberosLoginIdleCallback, 101); +} + +void TestKerberosRealms (void) +{ + printf ("About to test Kerberos realms\n"); + KLRemoveAllKerberosRealms (); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLInsertKerberosRealm (realmList_End, "FOO"); + KLInsertKerberosRealm (realmList_End, "BAR"); + KLInsertKerberosRealm (realmList_End, "BAZ"); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLInsertKerberosRealm (realmList_End, "FOO"); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLSetKerberosRealm (0, "QUUX"); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLRemoveKerberosRealm (0); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLSetKerberosRealm (2, "TEST-KERBEROS-1.3.1"); + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + + KLRemoveAllKerberosRealms (); + KLInsertKerberosRealm (realmList_End, "TEST-KERBEROS-1.3.1"); + KLInsertKerberosRealm (realmList_End, "TEST-KERBEROS-1.0.6"); + KLInsertKerberosRealm (realmList_End, "TESTV5-KERBEROS-1.0.6"); + KLInsertKerberosRealm (realmList_End, "TEST-KERBEROS-1.1.1"); + KLInsertKerberosRealm (realmList_End, "TESTV5-KERBEROS-1.1.1"); + KLInsertKerberosRealm (realmList_End, "TEST-KERBEROS-1.2.0"); + KLInsertKerberosRealm (realmList_End, "TESTV5-KERBEROS-1.2.0"); + KLInsertKerberosRealm (realmList_End, "TEST-HEIMDAL-0.3D"); + KLInsertKerberosRealm (realmList_End, "TESTV5-HEIMDAL-0.3D"); + KLInsertKerberosRealm (realmList_End, "TEST-KTH-KRB-1.1"); +} + + +void TestLoginOptions (void) +{ + KLBoolean optionSetting; + KLStatus err = klNoErr; + KLLifetime lifetime; + + lifetime = 10*60; + KLSetDefaultLoginOption(loginOption_MinimalTicketLifetime, &lifetime, sizeof(KLLifetime)); + + lifetime = 8*60*60; + KLSetDefaultLoginOption(loginOption_MaximalTicketLifetime, &lifetime, sizeof(KLLifetime)); + + lifetime = 8*60*60; + KLSetDefaultLoginOption(loginOption_DefaultTicketLifetime, &lifetime, sizeof(KLLifetime)); + + optionSetting = FALSE; + KLSetDefaultLoginOption(loginOption_DefaultForwardableTicket, &optionSetting, sizeof(optionSetting)); + + optionSetting = TRUE; + KLSetDefaultLoginOption(loginOption_RememberPrincipal, &optionSetting, sizeof(optionSetting)); + + optionSetting = TRUE; + err = KLSetDefaultLoginOption(loginOption_RememberExtras, &optionSetting, sizeof(optionSetting)); + + if (err == klNoErr) { + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + optionSetting = TRUE; + KLAcquireNewInitialTickets (NULL, NULL, NULL, NULL); + } +} + + +/* Lame date formatting stolen from CCacheDump, like ctime but with no \n */ + +static const char *day_name[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + +static const char *month_name[] = {"January", "February", "March","April","May","June", +"July", "August", "September", "October", "November","December"}; + +char* TimeToString (char* timeString, long t) +{ + /* we come in in 1970 time */ + time_t timer = (time_t) t; + struct tm tm; + + tm = *localtime (&timer); + + sprintf(timeString, "%.3s %.3s%3d %.2d:%.2d:%.2d %d", + day_name[tm.tm_wday], + month_name[tm.tm_mon], + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec, + tm.tm_year + 1900); + + return timeString; +} + + +void MyKerberosLoginIdleCallback (KLRefCon inAppData) +{ + syslog (LOG_ALERT, "App got callback while waiting for Mach IPC (appData == %d)\n", inAppData); + // KLCancelAllDialogs (); +} + diff --git a/krb5-1-7/src/kim/test/test_kll_terminal.c b/krb5-1-7/src/kim/test/test_kll_terminal.c new file mode 100644 index 000000000..9c22625bf --- /dev/null +++ b/krb5-1-7/src/kim/test/test_kll_terminal.c @@ -0,0 +1,39 @@ +#include + + + +int main (void) +{ + KLStatus err; + KLPrincipal principal; + char *principalName; + char *cacheName; + + printf ("Testing KLAcquireNewTickets (nil)...\n"); + + err = KLAcquireNewTickets (nil, &principal, &cacheName); + if (err == klNoErr) { + err = KLGetStringFromPrincipal (principal, kerberosVersion_V5, &principalName); + if (err == klNoErr) { + printf ("Got tickets for '%s' in cache '%s'\n", principalName, cacheName); + KLDisposeString (principalName); + } else { + printf ("KLGetStringFromPrincipal() returned (err = %ld)\n", err); + } + KLDisposeString (cacheName); + + printf ("Testing KLChangePassword (principal)...\n"); + + err = KLChangePassword (principal); + if (err != klNoErr) { + printf ("KLChangePassword() returned (err = %ld)\n", err); + } + + KLDisposePrincipal (principal); + } else { + printf ("KLAcquireNewTickets() returned (err = %ld)\n", err); + } + + printf ("All done testing!\n"); + return 0; +} \ No newline at end of file diff --git a/krb5-1-7/src/kim/test/test_ui_plugin.c b/krb5-1-7/src/kim/test/test_ui_plugin.c new file mode 100644 index 000000000..9a6e3761d --- /dev/null +++ b/krb5-1-7/src/kim/test/test_ui_plugin.c @@ -0,0 +1,472 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + + +typedef struct { + const char *magic; + aslclient asl_context; + int got_error; +} *test_ui_context; + +const char *magic = "test_ui_context_magic"; + +/* ------------------------------------------------------------------------ */ + +static void test_ui_vlog (test_ui_context in_context, + const char *in_format, + va_list in_args) +{ + if (!in_context) { + asl_log (NULL, NULL, ASL_LEVEL_ERR, "NULL context!"); + + } else if (strcmp (in_context->magic, magic)) { + asl_log (NULL, NULL, ASL_LEVEL_ERR, + "Magic mismatch. Context corrupted!"); + + } else { + asl_vlog (in_context->asl_context, NULL, ASL_LEVEL_NOTICE, + in_format, in_args); + } +} + +/* ------------------------------------------------------------------------ */ + +static void test_ui_log_ (void *in_context, + const char *in_function, + const char *in_format, ...) +{ + test_ui_context context = in_context; + char *format = NULL; + va_list args; + + asprintf (&format, "%s: %s", in_function, in_format); + + va_start (args, in_format); + test_ui_vlog (context, format, args); + va_end (args); + + free (format); +} + +#define test_ui_log(context, format, ...) test_ui_log_(context, __FUNCTION__, format, ## __VA_ARGS__) + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_init (void **out_context) +{ + kim_error err = KIM_NO_ERROR; + test_ui_context context = NULL; + + if (!err) { + context = malloc (sizeof (*context)); + if (!context) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + context->got_error = 0; + context->magic = magic; + context->asl_context = asl_open (NULL, + "com.apple.console", + ASL_OPT_NO_DELAY | ASL_OPT_STDERR); + if (!context->asl_context) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + test_ui_log (context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (NULL, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + if (!err) { + *out_context = context; + context = NULL; + } + + free (context); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_enter_identity (void *in_context, + kim_options io_options, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + + test_ui_log (in_context, "entering..."); + + if (!err) { + test_ui_context context = in_context; + if (context->got_error > 1) { + test_ui_log (in_context, "\tfailed twice, giving up..."); + context->got_error = 0; + err = KIM_USER_CANCELED_ERR; + } + } + + if (!err) { + err = kim_options_set_lifetime (io_options, 1800); + } + + if (!err) { + err = kim_options_set_renewal_lifetime (io_options, 3600); + } + + if (!err) { + err = kim_identity_create_from_string (&identity, + "nobody@TEST-KERBEROS-1.5"); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + *out_change_password = 0; + } + + kim_identity_free (&identity); + + if (!err) { + test_ui_log (in_context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (in_context, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_select_identity (void *in_context, + kim_selection_hints io_hints, + kim_identity *out_identity, + kim_boolean *out_change_password) +{ + kim_error err = KIM_NO_ERROR; + kim_identity identity = NULL; + kim_options options = NULL; + + test_ui_log (in_context, "entering..."); + + if (!err) { + test_ui_context context = in_context; + if (context->got_error > 1) { + test_ui_log (in_context, "\tfailed twice, giving up..."); + context->got_error = 0; + err = KIM_USER_CANCELED_ERR; + } + } + + if (!err) { + err = kim_selection_hints_get_options (io_hints, &options); + } + + if (!err && !options) { + err = kim_options_create (&options); + } + + if (!err) { + err = kim_options_set_lifetime (options, 1800); + } + + if (!err) { + err = kim_options_set_renewal_lifetime (options, 3600); + } + + if (!err) { + err = kim_selection_hints_set_options (io_hints, options); + } + + if (!err) { + err = kim_identity_create_from_string (&identity, + "nobody@TEST-KERBEROS-1.5"); + } + + if (!err) { + *out_identity = identity; + identity = NULL; + *out_change_password = 0; + } + + kim_options_free (&options); + kim_identity_free (&identity); + + if (!err) { + test_ui_log (in_context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (in_context, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_auth_prompt (void *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + char *reply = NULL; + + test_ui_log (in_context, "entering..."); + + if (!err) { + err = kim_identity_get_display_string (in_identity, &string); + } + + if (!err) { + test_ui_log (in_context, "\tidentity = %s", string); + test_ui_log (in_context, "\ttype = %d", in_type); + test_ui_log (in_context, "\tallow_save_reply = %d", in_allow_save_reply); + test_ui_log (in_context, "\thide_reply = %d", in_hide_reply); + test_ui_log (in_context, "\ttitle = %s", in_title); + test_ui_log (in_context, "\tmessage = %s", in_message); + test_ui_log (in_context, "\tdescription = %s", in_description); + + reply = strdup ("ydobon"); + if (!reply) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + test_ui_context context = in_context; + if (context->got_error > 1) { + test_ui_log (in_context, "\tfailed twice, giving up..."); + context->got_error = 0; + err = KIM_USER_CANCELED_ERR; + } + } + + if (!err) { + *out_reply = reply; + reply = NULL; + *out_save_reply = 0; + } + + free (reply); + kim_string_free (&string); + + if (!err) { + test_ui_log (in_context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (in_context, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_change_password (void *in_context, + kim_identity in_identity, + kim_boolean in_old_password_expired, + char **out_old_password, + char **out_new_password, + char **out_verify_password) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + char *old_password = NULL; + char *new_password = NULL; + char *vfy_password = NULL; + + test_ui_log (in_context, "entering..."); + + if (!err) { + err = kim_identity_get_display_string (in_identity, &string); + } + + if (!err) { + test_ui_log (in_context, "\tidentity = %s", string); + test_ui_log (in_context, "\told_password_expired = %d", + in_old_password_expired); + + old_password = strdup ("ydobon"); + new_password = strdup ("foo"); + vfy_password = strdup ("foo"); + if (!old_password || !new_password || !vfy_password) { + err = KIM_OUT_OF_MEMORY_ERR; + } + } + + if (!err) { + test_ui_context context = in_context; + if (context->got_error > 1) { + test_ui_log (in_context, "\tfailed twice, giving up..."); + context->got_error = 0; + err = KIM_USER_CANCELED_ERR; + } + } + + if (!err) { + *out_old_password = old_password; + old_password = NULL; + *out_new_password = new_password; + new_password = NULL; + *out_verify_password = vfy_password; + vfy_password = NULL; + } + + free (old_password); + free (new_password); + free (vfy_password); + kim_string_free (&string); + + if (!err) { + test_ui_log (in_context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (in_context, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_handle_error (void *in_context, + kim_identity in_identity, + kim_error in_error, + kim_string in_error_message, + kim_string in_error_description) +{ + kim_error err = KIM_NO_ERROR; + kim_string string = NULL; + + test_ui_log (in_context, "entering..."); + + if (!err) { + err = kim_identity_get_display_string (in_identity, &string); + } + + if (!err) { + test_ui_context context = in_context; + + test_ui_log (in_context, "\tidentity = %s", string); + test_ui_log (in_context, "\terror = %d", in_error); + test_ui_log (in_context, "\tmessage = %s", in_error_message); + test_ui_log (in_context, "\tdescription = %s", in_error_description); + + context->got_error++; + } + + kim_string_free (&string); + + if (!err) { + test_ui_log (in_context, "returning with no error."); + } else { + kim_string estring = NULL; + + kim_string_create_for_last_error (&estring, err); + test_ui_log (in_context, "returning %d: %s", err, estring); + kim_string_free (&estring); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void test_ui_free_string (void *in_context, + char **io_string) +{ + /* strings zeroed by caller so just print pointer value */ + test_ui_log (in_context, "freeing string %p", *io_string); + + free (*io_string); + *io_string = NULL; +} + +/* ------------------------------------------------------------------------ */ + +static kim_error test_ui_fini (void *io_context) +{ + kim_error err = KIM_NO_ERROR; + + test_ui_log (io_context, "deallocating..."); + + if (io_context) { + test_ui_context context = io_context; + + asl_close (context->asl_context); + free (context); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +kim_ui_plugin_ftable_v0 kim_ui_0 = { + 0, + test_ui_init, + test_ui_enter_identity, + test_ui_select_identity, + test_ui_auth_prompt, + test_ui_change_password, + test_ui_handle_error, + test_ui_free_string, + test_ui_fini +}; diff --git a/krb5-1-7/src/krb5-config.M b/krb5-1-7/src/krb5-config.M new file mode 100644 index 000000000..56661aee7 --- /dev/null +++ b/krb5-1-7/src/krb5-config.M @@ -0,0 +1,73 @@ +.\" 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 +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-7/src/krb5-config.in b/krb5-1-7/src/krb5-config.in new file mode 100755 index 000000000..1952ccb5c --- /dev/null +++ b/krb5-1-7/src/krb5-config.in @@ -0,0 +1,223 @@ +#!/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@' +KDB5_DB_LIB=@KDB5_DB_LIB@ +LDFLAGS='@LDFLAGS@' +RPATH_FLAG='@RPATH_FLAG@' +PROG_RPATH_FLAGS='@PROG_RPATH_FLAGS@' +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 + ;; + 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 " 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 + # Assumes /usr/lib is the standard library directory everywhere... + if test "$libdir" = /usr/lib; then + libdirarg= + else + libdirarg="-L$libdir" + fi + # Ugly gross hack for our build tree + lib_flags=`echo $CC_LINK | sed -e 's/\$(CC)//' \ + -e 's/\$(PURE)//' \ + -e 's#\$(PROG_RPATH_FLAGS)#'"$PROG_RPATH_FLAGS"'#' \ + -e 's#\$(PROG_RPATH)#'$libdir'#' \ + -e 's#\$(PROG_LIBPATH)#'$libdirarg'#' \ + -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 = '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-7/src/lib/Makefile.in b/krb5-1-7/src/lib/Makefile.in new file mode 100644 index 000000000..f5180d7c2 --- /dev/null +++ b/krb5-1-7/src/lib/Makefile.in @@ -0,0 +1,194 @@ +thisconfigdir=./.. +myfulldir=lib +mydir=lib +SUBDIRS=crypto krb5 gssapi rpc kdb kadm5 apputils +BUILDTOP=$(REL).. + +all-unix:: + +CLEANLIBS = libkrb5.a libkdb5.a libcrypto.a libgssapi_krb5.a libkadm.a \ + libcom_err.a libpty.a ibss.a libgssapi.a libapputils.a libkrb5.so \ + libcrypto.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-7/src/lib/apputils/Makefile.in b/krb5-1-7/src/lib/apputils/Makefile.in new file mode 100644 index 000000000..07d7aa3c4 --- /dev/null +++ b/krb5-1-7/src/lib/apputils/Makefile.in @@ -0,0 +1,38 @@ +prefix=@prefix@ +bindir=@bindir@ +datadir=@datadir@ +mydatadir=$(datadir)/apputils +thisconfigdir=../.. +myfulldir=lib/apputils +mydir=lib/apputils +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 + +@libpriv_frag@ +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/apputils/daemon.c b/krb5-1-7/src/lib/apputils/daemon.c new file mode 100644 index 000000000..00dde4882 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#ifdef HAVE_PATHS_H +#include +#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-7/src/lib/apputils/deps b/krb5-1-7/src/lib/apputils/deps new file mode 100644 index 000000000..93b7a2f04 --- /dev/null +++ b/krb5-1-7/src/lib/apputils/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/apputils/dummy.c b/krb5-1-7/src/lib/apputils/dummy.c new file mode 100644 index 000000000..d5b6cc08d --- /dev/null +++ b/krb5-1-7/src/lib/apputils/dummy.c @@ -0,0 +1 @@ +int lib_server_dummy = 0; diff --git a/krb5-1-7/src/lib/comerr32.def b/krb5-1-7/src/lib/comerr32.def new file mode 100644 index 000000000..55c024d1a --- /dev/null +++ b/krb5-1-7/src/lib/comerr32.def @@ -0,0 +1,12 @@ +;LIBRARY COMERR32 +DESCRIPTION 'DLL for ComErr' +HEAPSIZE 8192 + +EXPORTS + com_err @2 + com_err_va @3 + error_message @4 + add_error_table @1 + remove_error_table @5 + set_com_err_hook @6 + reset_com_err_hook @7 diff --git a/krb5-1-7/src/lib/crypto/ISSUES b/krb5-1-7/src/lib/crypto/ISSUES new file mode 100644 index 000000000..c2122805d --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/Makefile.in b/krb5-1-7/src/lib/crypto/Makefile.in new file mode 100644 index 000000000..61bbc1f21 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/Makefile.in @@ -0,0 +1,403 @@ +thisconfigdir=../.. +myfulldir=lib/crypto +mydir=lib/crypto +BUILDTOP=$(REL)..$(S).. +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 -I$(srcdir)/md5 +RUN_SETUP = @KRB5_RUN_ENV@ +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) +DEFS= + +EXTRADEPSRCS=\ + $(srcdir)/t_nfold.c \ + $(srcdir)/t_cf2.c \ + $(srcdir)/t_encrypt.c \ + $(srcdir)/t_short.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=\ + aead.o \ + block_size.o \ + cf2.o \ + checksum_length.o \ + cksumtype_to_string.o \ + cksumtypes.o \ + coll_proof_cksum.o \ + combine_keys.o \ + crypto_length.o \ + crypto_libinit.o \ + default_state.o \ + decrypt.o \ + decrypt_iov.o \ + encrypt.o \ + encrypt_iov.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_checksum_iov.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 \ + verify_checksum_iov.o + +OBJS=\ + $(OUTPRE)aead.$(OBJEXT) \ + $(OUTPRE)block_size.$(OBJEXT) \ + $(OUTPRE)cf2$(OBJEXT) \ + $(OUTPRE)checksum_length.$(OBJEXT) \ + $(OUTPRE)cksumtype_to_string.$(OBJEXT) \ + $(OUTPRE)cksumtypes.$(OBJEXT) \ + $(OUTPRE)coll_proof_cksum.$(OBJEXT) \ + $(OUTPRE)combine_keys.$(OBJEXT) \ + $(OUTPRE)crypto_length.$(OBJEXT) \ + $(OUTPRE)crypto_libinit.$(OBJEXT) \ + $(OUTPRE)default_state.$(OBJEXT) \ + $(OUTPRE)decrypt.$(OBJEXT) \ + $(OUTPRE)decrypt_iov.$(OBJEXT) \ + $(OUTPRE)encrypt.$(OBJEXT) \ + $(OUTPRE)encrypt_iov.$(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_checksum_iov.$(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) \ + $(OUTPRE)verify_checksum_iov.$(OBJEXT) + +SRCS=\ + $(srcdir)/aead.c \ + $(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_length.c \ + $(srcdir)/crypto_libinit.c \ + $(srcdir)/default_state.c \ + $(srcdir)/decrypt.c \ + $(srcdir)/decrypt_iov.c \ + $(srcdir)/encrypt.c \ + $(srcdir)/encrypt_iov.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_checksum_iov.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)/cf2.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 \ + $(srcdir)/verify_checksum_iov.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) @CRYPTO_LIBS@ $(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 t_cf2 t_short + $(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_prf <$(srcdir)/t_prf.in >t_prf.output + diff t_prf.output $(srcdir)/t_prf.expected + $(RUN_SETUP) $(VALGRIND) ./t_cf2 <$(srcdir)/t_cf2.in >t_cf2.output + diff t_cf2.output $(srcdir)/t_cf2.expected + $(RUN_SETUP) $(VALGRIND) ./t_short + + +# $(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_cf2$(EXEEXT): t_cf2.$(OBJEXT) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ t_cf2.$(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) + +t_short$(EXEEXT): t_short.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ t_short.$(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 \ + t_cf2 t_cf2.o t_short t_short.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@ + diff --git a/krb5-1-7/src/lib/crypto/aead.c b/krb5-1-7/src/lib/crypto/aead.c new file mode 100644 index 000000000..2d9a8353a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aead.c @@ -0,0 +1,573 @@ +/* + * lib/crypto/aead.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#include "cksumtypes.h" +#include "dk.h" +#include "aead.h" + +krb5_crypto_iov * +krb5int_c_locate_iov(krb5_crypto_iov *data, + size_t num_data, + krb5_cryptotype type) +{ + size_t i; + krb5_crypto_iov *iov = NULL; + + if (data == NULL) + return NULL; + + for (i = 0; i < num_data; i++) { + if (data[i].flags == type) { + if (iov == NULL) + iov = &data[i]; + else + return NULL; /* can't appear twice */ + } + } + + return iov; +} + +static krb5_error_code +make_unkeyed_checksum_iov(const struct krb5_hash_provider *hash_provider, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output) +{ + krb5_data *sign_data; + size_t num_sign_data; + krb5_error_code ret; + size_t i, j; + + /* Create a checksum over all the data to be signed */ + for (i = 0, num_sign_data = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + num_sign_data++; + } + + /* XXX cleanup to avoid alloc */ + sign_data = (krb5_data *)calloc(num_sign_data, sizeof(krb5_data)); + if (sign_data == NULL) + return ENOMEM; + + for (i = 0, j = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + sign_data[j++] = iov->data; + } + + ret = hash_provider->hash(num_sign_data, sign_data, output); + + free(sign_data); + + return ret; +} + +krb5_error_code +krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum_type, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *cksum_data) +{ + int e1, e2; + krb5_error_code ret; + + if (cksum_type->keyhash != NULL) { + /* check if key is compatible */ + + if (cksum_type->keyed_etype) { + for (e1=0; e1keyed_etype) + break; + + for (e2=0; e2enctype) + 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; + } + } + + if (cksum_type->keyhash->hash_iov == NULL) { + return KRB5_BAD_ENCTYPE; + } + + ret = (*(cksum_type->keyhash->hash_iov))(key, usage, 0, + data, num_data, cksum_data); + } else if (cksum_type->flags & KRB5_CKSUMFLAG_DERIVE) { + ret = krb5int_dk_make_checksum_iov(cksum_type->hash, + key, usage, data, num_data, + cksum_data); + } else { + ret = make_unkeyed_checksum_iov(cksum_type->hash, data, num_data, + cksum_data); + } + + if (ret == 0) { + if (cksum_type->trunc_size) { + cksum_data->length = cksum_type->trunc_size; + } + } + +cleanup: + if (ret != 0) { + memset(cksum_data->data, 0, cksum_data->length); + } + + return ret; +} + +const struct krb5_cksumtypes * +krb5int_c_find_checksum_type(krb5_cksumtype cksumtype) +{ + size_t i; + + for (i = 0; i < krb5_cksumtypes_length; i++) { + if (krb5_cksumtypes_list[i].ctype == cksumtype) + break; + } + + if (i == krb5_cksumtypes_length) + return NULL; + + return &krb5_cksumtypes_list[i]; +} + +#ifdef DEBUG_IOV +static void +dump_block(const char *tag, + size_t i, + size_t j, + unsigned char *block, + size_t block_size) +{ + size_t k; + + printf("[%s: %d.%d] ", tag, i, j); + + for (k = 0; k < block_size; k++) + printf("%02x ", block[k] & 0xFF); + + printf("\n"); +} +#endif + +static int +process_block_p(const krb5_crypto_iov *data, + size_t num_data, + struct iov_block_state *iov_state, + size_t i) +{ + const krb5_crypto_iov *iov = &data[i]; + int process_block; + + switch (iov->flags) { + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + process_block = iov_state->include_sign_only; + break; + case KRB5_CRYPTO_TYPE_PADDING: + process_block = (iov_state->pad_to_boundary == 0); + break; + case KRB5_CRYPTO_TYPE_HEADER: + process_block = (iov_state->ignore_header == 0); + break; + case KRB5_CRYPTO_TYPE_DATA: + process_block = 1; + break; + default: + process_block = 0; + break; + } + + return process_block; +} + +/* + * Returns TRUE if, having reached the end of the current buffer, + * we should pad the rest of the block with zeros. + */ +static int +pad_to_boundary_p(const krb5_crypto_iov *data, + size_t num_data, + struct iov_block_state *iov_state, + size_t i, + size_t j) +{ + /* If the pad_to_boundary flag is unset, return FALSE */ + if (iov_state->pad_to_boundary == 0) + return 0; + + /* If we haven't got any data, we need to get some */ + if (j == 0) + return 0; + + /* No boundary between adjacent buffers marked for processing */ + if (data[iov_state->iov_pos].flags == data[i].flags) + return 0; + + return 1; +} + +krb5_boolean +krb5int_c_iov_get_block(unsigned char *block, + size_t block_size, + const krb5_crypto_iov *data, + size_t num_data, + struct iov_block_state *iov_state) +{ + size_t i, j = 0; + + for (i = iov_state->iov_pos; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + size_t nbytes; + + if (!process_block_p(data, num_data, iov_state, i)) + continue; + + if (pad_to_boundary_p(data, num_data, iov_state, i, j)) + break; + + iov_state->iov_pos = i; + + nbytes = iov->data.length - iov_state->data_pos; + if (nbytes > block_size - j) + nbytes = block_size - j; + + memcpy(block + j, iov->data.data + iov_state->data_pos, nbytes); + + iov_state->data_pos += nbytes; + j += nbytes; + + assert(j <= block_size); + + if (j == block_size) + break; + + assert(iov_state->data_pos == iov->data.length); + + iov_state->data_pos = 0; + } + + iov_state->iov_pos = i; + + if (j != block_size) + memset(block + j, 0, block_size - j); + +#ifdef DEBUG_IOV + dump_block("get_block", i, j, block, block_size); +#endif + + return (iov_state->iov_pos < num_data); +} + +krb5_boolean +krb5int_c_iov_put_block(const krb5_crypto_iov *data, + size_t num_data, + unsigned char *block, + size_t block_size, + struct iov_block_state *iov_state) +{ + size_t i, j = 0; + + for (i = iov_state->iov_pos; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + size_t nbytes; + + if (!process_block_p(data, num_data, iov_state, i)) + continue; + + if (pad_to_boundary_p(data, num_data, iov_state, i, j)) + break; + + iov_state->iov_pos = i; + + nbytes = iov->data.length - iov_state->data_pos; + if (nbytes > block_size - j) + nbytes = block_size - j; + + memcpy(iov->data.data + iov_state->data_pos, block + j, nbytes); + + iov_state->data_pos += nbytes; + j += nbytes; + + assert(j <= block_size); + + if (j == block_size) + break; + + assert(iov_state->data_pos == iov->data.length); + + iov_state->data_pos = 0; + } + + iov_state->iov_pos = i; + +#ifdef DEBUG_IOV + dump_block("put_block", i, j, block, block_size); +#endif + + return (iov_state->iov_pos < num_data); +} + +krb5_error_code +krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + unsigned int header_len, trailer_len, padding_len; + krb5_crypto_iov *iov; + krb5_crypto_iov *stream; + size_t i, j; + int got_data = 0; + + stream = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM); + assert(stream != NULL); + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_HEADER, &header_len); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &trailer_len); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &padding_len); + if (ret != 0) + return ret; + + if (stream->data.length < header_len + trailer_len) + return KRB5_BAD_MSIZE; + + iov = (krb5_crypto_iov *)calloc(num_data + 2, sizeof(krb5_crypto_iov)); + if (iov == NULL) + return ENOMEM; + + i = 0; + + iov[i].flags = KRB5_CRYPTO_TYPE_HEADER; /* takes place of STREAM */ + iov[i].data.data = stream->data.data; + iov[i].data.length = header_len; + i++; + + for (j = 0; j < num_data; j++) { + if (data[j].flags == KRB5_CRYPTO_TYPE_DATA) { + if (got_data) { + free(iov); + return KRB5_BAD_MSIZE; + } + + got_data++; + + data[j].data.data = stream->data.data + header_len; + data[j].data.length = stream->data.length - header_len - trailer_len; + } + if (data[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY || + data[j].flags == KRB5_CRYPTO_TYPE_DATA) + iov[i++] = data[j]; + } + + /* XXX not self-describing with respect to length, this is the best we can do */ + iov[i].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[i].data.data = NULL; + iov[i].data.length = 0; + i++; + + iov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[i].data.data = stream->data.data + stream->data.length - trailer_len; + iov[i].data.length = trailer_len; + i++; + + assert(i <= num_data + 2); + + ret = aead->decrypt_iov(aead, enc, hash, key, keyusage, ivec, iov, i); + + free(iov); + + return ret; +} + +krb5_error_code +krb5int_c_padding_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t data_length, + unsigned int *pad_length) +{ + unsigned int padding; + krb5_error_code ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &padding); + if (ret != 0) + return ret; + + if (padding == 0 || (data_length % padding) == 0) + *pad_length = 0; + else + *pad_length = padding - (data_length % padding); + + return 0; +} + +krb5_error_code +krb5int_c_encrypt_aead_compat(const struct krb5_aead_provider *aead, + 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_crypto_iov iov[4]; + krb5_error_code ret; + unsigned int header_len = 0; + unsigned int padding_len = 0; + unsigned int trailer_len = 0; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_HEADER, + &header_len); + if (ret != 0) + return ret; + + ret = krb5int_c_padding_length(aead, enc, hash, input->length, &padding_len); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, + &trailer_len); + if (ret != 0) + return ret; + + if (output->length < header_len + input->length + padding_len + trailer_len) + return KRB5_BAD_MSIZE; + + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data.data = output->data; + iov[0].data.length = header_len; + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = iov[0].data.data + iov[0].data.length; + iov[1].data.length = input->length; + memcpy(iov[1].data.data, input->data, input->length); + + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data.data = iov[1].data.data + iov[1].data.length; + iov[2].data.length = padding_len; + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data.data = iov[2].data.data + iov[2].data.length; + iov[3].data.length = trailer_len; + + ret = aead->encrypt_iov(aead, enc, hash, key, + usage, ivec, + iov, sizeof(iov)/sizeof(iov[0])); + + if (ret != 0) + zap(iov[1].data.data, iov[1].data.length); + + output->length = iov[0].data.length + iov[1].data.length + + iov[2].data.length + iov[3].data.length; + + return ret; +} + +krb5_error_code +krb5int_c_decrypt_aead_compat(const struct krb5_aead_provider *aead, + 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_crypto_iov iov[2]; + krb5_error_code ret; + + iov[0].flags = KRB5_CRYPTO_TYPE_STREAM; + iov[0].data.data = malloc(input->length); + if (iov[0].data.data == NULL) + return ENOMEM; + + memcpy(iov[0].data.data, input->data, input->length); + iov[0].data.length = input->length; + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = NULL; + iov[1].data.length = 0; + + ret = krb5int_c_iov_decrypt_stream(aead, enc, hash, key, + usage, ivec, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + goto cleanup; + + if (output->length < iov[1].data.length) { + ret = KRB5_BAD_MSIZE; + goto cleanup; + } + + memcpy(output->data, iov[1].data.data, iov[1].data.length); + output->length = iov[1].data.length; + +cleanup: + zap(iov[0].data.data, iov[0].data.length); + free(iov[0].data.data); + + return ret; +} + +void +krb5int_c_encrypt_length_aead_compat(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length) +{ + unsigned int header_len = 0; + unsigned int padding_len = 0; + unsigned int trailer_len = 0; + + aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_HEADER, &header_len); + krb5int_c_padding_length(aead, enc, hash, inputlen, &padding_len); + aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &trailer_len); + + *length = header_len + inputlen + padding_len + trailer_len; +} + diff --git a/krb5-1-7/src/lib/crypto/aead.h b/krb5-1-7/src/lib/crypto/aead.h new file mode 100644 index 000000000..2c99eb868 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aead.h @@ -0,0 +1,123 @@ +/* + * lib/crypto/aead.h + * + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "cksumtypes.h" + +/* AEAD helpers */ + +krb5_crypto_iov * +krb5int_c_locate_iov(krb5_crypto_iov *data, + size_t num_data, + krb5_cryptotype type); + +krb5_error_code +krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *cksum_data); + +const struct krb5_cksumtypes * +krb5int_c_find_checksum_type(krb5_cksumtype cksumtype); + +#define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER) + +#define ENCRYPT_DATA_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING) + +#define ENCRYPT_IOV(_iov) (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov)) + +#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY ) + +struct iov_block_state { + size_t iov_pos; /* index into iov array */ + size_t data_pos; /* index into iov contents */ + unsigned int ignore_header : 1; /* have/should we process HEADER */ + unsigned int include_sign_only : 1; /* should we process SIGN_ONLY blocks */ + unsigned int pad_to_boundary : 1; /* should we zero fill blocks until next buffer */ +}; + +#define IOV_BLOCK_STATE_INIT(_state) ((_state)->iov_pos = \ + (_state)->data_pos = \ + (_state)->ignore_header = \ + (_state)->include_sign_only = \ + (_state)->pad_to_boundary = 0) + +krb5_boolean +krb5int_c_iov_get_block(unsigned char *block, + size_t block_size, + const krb5_crypto_iov *data, + size_t num_data, + struct iov_block_state *iov_state); + +krb5_boolean +krb5int_c_iov_put_block(const krb5_crypto_iov *data, + size_t num_data, + unsigned char *block, + size_t block_size, + struct iov_block_state *iov_state); + +krb5_error_code +krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); + +krb5_error_code +krb5int_c_decrypt_aead_compat(const struct krb5_aead_provider *aead, + 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 +krb5int_c_encrypt_aead_compat(const struct krb5_aead_provider *aead, + 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_c_encrypt_length_aead_compat(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length); + +krb5_error_code +krb5int_c_padding_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t data_length, + unsigned int *pad_length); diff --git a/krb5-1-7/src/lib/crypto/aes/Makefile.in b/krb5-1-7/src/lib/crypto/aes/Makefile.in new file mode 100644 index 000000000..4ed8ef7bf --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/Makefile.in @@ -0,0 +1,72 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/aes/aes-gen.c b/krb5-1-7/src/lib/crypto/aes/aes-gen.c new file mode 100644 index 000000000..855e6a470 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#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-7/src/lib/crypto/aes/aes-test.c b/krb5-1-7/src/lib/crypto/aes/aes-test.c new file mode 100644 index 000000000..c05fd26e3 --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/crypto/aes/aes.h b/krb5-1-7/src/lib/crypto/aes/aes.h new file mode 100644 index 000000000..ac1c1b89e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aes.h @@ -0,0 +1,97 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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-7/src/lib/crypto/aes/aes.txt b/krb5-1-7/src/lib/crypto/aes/aes.txt new file mode 100644 index 000000000..b644b5eb4 --- /dev/null +++ b/krb5-1-7/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 is a two digit +number): + +1. ecbvk.txt ECB vectors with variable key +2. ecbvt.txt ECB vectors with variable text +3. ecbnk.txt new ECB vectors with variable key +4. ecbnt.txt new ECB vectors with variable text +5. ecbme.txt ECB monte carlo encryption test vectors +6. ecbmd.txt ECB monte carlo decryption test vectors +7. cbcme.txt CBC monte carlo encryption test vectors +8. cbcmd.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 \ No newline at end of file diff --git a/krb5-1-7/src/lib/crypto/aes/aes_s2k.c b/krb5-1-7/src/lib/crypto/aes/aes_s2k.c new file mode 100644 index 000000000..30ca27501 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aes_s2k.c @@ -0,0 +1,90 @@ +/* + * 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 = load_32_be(p); + 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-7/src/lib/crypto/aes/aes_s2k.h b/krb5-1-7/src/lib/crypto/aes/aes_s2k.h new file mode 100644 index 000000000..b6804a991 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/aescpp.h b/krb5-1-7/src/lib/crypto/aes/aescpp.h new file mode 100644 index 000000000..e685485e1 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aescpp.h @@ -0,0 +1,55 @@ + +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman , 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-7/src/lib/crypto/aes/aescrypp.c b/krb5-1-7/src/lib/crypto/aes/aescrypp.c new file mode 100644 index 000000000..87b634179 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aescrypp.c @@ -0,0 +1,487 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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-7/src/lib/crypto/aes/aescrypt.asm b/krb5-1-7/src/lib/crypto/aes/aescrypt.asm new file mode 100644 index 000000000..35a6818b6 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aescrypt.asm @@ -0,0 +1,402 @@ + +; ------------------------------------------------------------------------- +; 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. +; ------------------------------------------------------------------------- +; Issue Date: 15/01/2002 + +; An AES (Rijndael) implementation for the Pentium MMX family using the NASM +; assembler . 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-7/src/lib/crypto/aes/aescrypt.c b/krb5-1-7/src/lib/crypto/aes/aescrypt.c new file mode 100644 index 000000000..9db66e284 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aescrypt.c @@ -0,0 +1,421 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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-7/src/lib/crypto/aes/aeskey.c b/krb5-1-7/src/lib/crypto/aes/aeskey.c new file mode 100644 index 000000000..60f766b8a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aeskey.c @@ -0,0 +1,369 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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: ss[4] = word_in(in_key + 16); + cx->k_sch[4] = ff(ss[4]); + ss[5] = word_in(in_key + 20); + cx->k_sch[5] = ff(ss[5]); + 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: ss[4] = word_in(in_key + 16); + cx->k_sch[4] = ff(ss[4]); + ss[5] = word_in(in_key + 20); + cx->k_sch[5] = ff(ss[5]); + ss[6] = word_in(in_key + 24); + cx->k_sch[6] = ff(ss[6]); + ss[7] = word_in(in_key + 28); + cx->k_sch[7] = ff(ss[7]); + 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-7/src/lib/crypto/aes/aeskeypp.c b/krb5-1-7/src/lib/crypto/aes/aeskeypp.c new file mode 100644 index 000000000..89fd9006d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aeskeypp.c @@ -0,0 +1,399 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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-7/src/lib/crypto/aes/aesopt.h b/krb5-1-7/src/lib/crypto/aes/aesopt.h new file mode 100644 index 000000000..006fbb3eb --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aesopt.h @@ -0,0 +1,851 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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 +# include +#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 +#elif defined(__m68k__) && defined(__palmos__) +# include /* 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 +# if defined(HAVE_ENDIAN_H) +# include +# elif defined(HAVE_MACHINE_ENDIAN_H) +# include +# else +# include +# 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) || defined(CONFIG_SMALL_NO_CRYPTO) +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +#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) || defined(CONFIG_SMALL_NO_CRYPTO) /* 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) || defined(CONFIG_SMALL_NO_CRYPTO) /* 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) || defined(CONFIG_SMALL_NO_CRYPTO) /* 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) || defined(CONFIG_SMALL_NO_CRYPTO) /* 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) || defined(CONFIG_SMALL_NO_CRYPTO) +#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-7/src/lib/crypto/aes/aessrc.url b/krb5-1-7/src/lib/crypto/aes/aessrc.url new file mode 100644 index 000000000..0758737db --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aessrc.url @@ -0,0 +1 @@ +http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm diff --git a/krb5-1-7/src/lib/crypto/aes/aestab.c b/krb5-1-7/src/lib/crypto/aes/aestab.c new file mode 100644 index 000000000..7a5d69f7d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/aestab.c @@ -0,0 +1,494 @@ +/* + ------------------------------------------------------------------------- + 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. + ------------------------------------------------------------------------- + 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-7/src/lib/crypto/aes/deps b/krb5-1-7/src/lib/crypto/aes/deps new file mode 100644 index 000000000..4434425fd --- /dev/null +++ b/krb5-1-7/src/lib/crypto/aes/deps @@ -0,0 +1,20 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/aes/expect-vk.txt b/krb5-1-7/src/lib/crypto/aes/expect-vk.txt new file mode 100644 index 000000000..bbd2c587b --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/expect-vt.txt b/krb5-1-7/src/lib/crypto/aes/expect-vt.txt new file mode 100644 index 000000000..02b238c04 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/Readme.txt b/krb5-1-7/src/lib/crypto/aes/test/Readme.txt new file mode 100644 index 000000000..69dbb5b9c --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/cbc_d_m.txt b/krb5-1-7/src/lib/crypto/aes/test/cbc_d_m.txt new file mode 100644 index 000000000..e216f3b87 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/cbc_e_m.txt b/krb5-1-7/src/lib/crypto/aes/test/cbc_e_m.txt new file mode 100644 index 000000000..cd344785f --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_d_m.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_d_m.txt new file mode 100644 index 000000000..d99a69af3 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_e_m.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_e_m.txt new file mode 100644 index 000000000..40a95e7ca --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_iv.readme b/krb5-1-7/src/lib/crypto/aes/test/ecb_iv.readme new file mode 100644 index 000000000..c37215768 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_iv.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_iv.txt new file mode 100644 index 000000000..3f6608e4e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_tbl.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_tbl.txt new file mode 100644 index 000000000..f1eef5300 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_vk.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_vk.txt new file mode 100644 index 000000000..5dfd60089 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/ecb_vt.txt b/krb5-1-7/src/lib/crypto/aes/test/ecb_vt.txt new file mode 100644 index 000000000..6dea60fc4 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/aes/test/katmct.pdf b/krb5-1-7/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#@rke%Slhy_-%|Qksp6otqL9jqc!Zb`cZpUnD@uN$F%}i-{&Ago(zX zXyIt(ZcWL>`7f*fuPtq3?{48r$)TvPBWVG3GPn45hlmI!nwz_;g{cE3S^zLIU_N}w zlARO6^b6DwQtBoytrgR-Uv5Pi}`75GSJ9=K84PQ19Y3p5Jzr$kNph>?&su;(TysnV6D z2mKXKweW^w)YXbW&ip`hOAR7L*$9`UXaJ2%bjv3OqUf6>z4r87b;=B^ z6PGHa8YtCs(%j{vsf5FL%m-VDB3dR#VVk!=wBJ~0b&jZ!G|BY z^6%(hOSq(w9J�n|Vb@R_I1>e2=vJ8yQij${dTyKXEG*>^3DJjDf!L)V+^*5JV^D zRuffR*&!4z5JAG648XwooetobLPg{$tis`}oR}MWz@VWVyP+{lpWrG(!>I}`jvf;Y zh6S#P^2Xe@O@ZqB;YL8L5_zIGylQKPKtMGfd%FbZ#u2QS^CFQ(z%f&{YtR{qKSFd) z5|3PbKP!r}U`8VMtnIo$nFN44g#knvWE>I@`w_MDBs>|yPS%DMz4A7AV?LEw%Y$xRO)CEh++Lh+F2op=@Wb`Q{fYjV`_7wEc1?t5l{{mhvakse48z4Cl9hV zA%>XqqE`rF-Y#2Sel!Tkwunznx^s(nAq-)j4mG1De7VLmQBapB9;!jVJ_zGj5~7jB z%lQj8%m{5%!E~0s^H7;h{J{gh+J?Nhh;u~EGE^U zR`l}MzJAZ`)@#z(&5PO9AuV zSPo+(XD&Z8S1@y12bzapfF+ykt; ziiM2zFMBG_M5$v^h>r3xnY_bj=Ony$z#$lCkyPPIIISmIWhREL53fp`myf$xx1j*B zoXZo>Bprt$L1o6VfH7Z1lwr|C>cP_CyH`(78og)NT?uj)9+r)z2N}X*>w)7q};+5aixyGu?>yI$bUvbbkcJwDc#9w|s;1Ru~}}a5+UlJ|i4FGKIp1cvSls<^>o?Ue=B&!<2;z z==g4wk#-YWCF6+=KP)z2j7C@FAIZIgGe#?auuVN1T3tq4EnYyX=xzeW_U3)3!^B0E zJiA;cr zq{ooWj|>l@8XVCPmWvmNaJcgqBi6&VdSpT#ABrEs8`=$&Le5fO=bQ|FmC)P96de!T z@0Nj?s|J2#are+}_UaVbG{-B}c+pspNKl0DYL0tYaZC()a$g(BG-BEQ9>O3Pdyb}F z7^q&55UGGoWuZ_W%>>gtd{%rP%2VOg*VUFrAXc%?8nEYMR z#ph-KW&dV^?J1?onLs5<9*G`vOO@TaKy7nm0rx}MXVVj z?^L3?YwEzZn}S~y?JEPCh-#+JG`~Y$nU83+ESO| z#s&-4ndDLDd;B!e=9&crOiQzPO-C6zo622CZjf4pI1^YhaZs+jif8*C#tdfZRONBP zTzee)5enJ}QR!>x6p2pll0t8Dy$9t^;i={{eaBI1lxHuQWsx@$sYIEB?+8&j zz|i7bCPhpHUxF^Q2szfQ{m-J^5Qv$&x1gC|eVq5t-WI1Q$szSTCe>LE10W$A-XnEt zSu;6_kHElvqek3Q&K^Hrv}8g-Te=6ar?@0CT)TIjXALl$;_ajYx?6 z2vJM=V-8hkp=Y6$KJRu7J-S@4Ez}WE*K9g|HN28eFE9HFIel zTUav+xsebfRuo+Cfr#U6rRy_&snEh8tu zCiU})9{Ia(y4Z8Xq5(Qf~xJ$-=Aj;$4%gq0bhRQHJQMN*m} zV4_(#n*UEd{R{s?um5oCKM^+%nCCww|7n5#UpCY9akil3P&Ku(_y;ppQ&$T|cS`X8 zaGJV>o0Eqt)WVJOKa7)h`giTWBTh=*|El@tHV$bnO1}RUb5rvFkNCel$D!)#1l6!` zr{w^nTKA&2sQL)Yf?zrsnFs)ziFVZCgImu@SOH(6g zI`P`Z3}4Yv3)#C^g+z}O$`ucp@x_l(Nd!7C$hvZeqxm|B2AFY^Ow(q*MKd@wZ(e)( zR6q0bbPUR>#;i&daRvMMZW)-vt}c(C zUvyDCSi&#C91RD*X{>QUFt)$}jA}O7f`w=r*}drL9?Xh^B*uK#_#$>O(L8z-mLqOb zfVHF`ZNxxcBr941P=BvKBB?2?S_K0{2FtG!q#9D-cO?PjPbo7>%4JOu4;F|DMlM8kg4^ z5>bS^KSi=L6lV=aG+jVsA*Py4XCSM-z&wk~cV%8oQdst)AzXCEX{wgNA>my@@W4YuC@TY^h@0e6MYy<|BqBGyytf_c zuX7+{*A5=nP*19GXV_Y0n|0szvK@9&Su z{q<*GsE@GbHBloqJ}o$LcUe}I;o#s4SbRkcU>dh@LBlw0tPq*FA=nNykMDDsP$q)4 z{PDXImar2d1$-y)BWjL`Uz=5Ct5`2#((eQp4Qy;K))YcHwQ|8Ru7B&!^l4TL?Orte zn_=VhIk~n}!BfG!@PIC&3y5}M$IaAJzq6wsiCnGyxTtL~+XYm6rN%7lH_^!rANo~~B3l&)r z>h#a|2N!dqB0MPwd8V1Iv){3>9sy0NL40g*E+tyk}5&@Z8oU6kHQ1vmtS94qVJ{zDB=_=q5RRn~q5a>_K z9f55KylC*_GkOddEgTuzLKadl*bJjG+}VrQIX znbTcwmSMoguK=ZT898j?D6SRDk+t)tFl21P(Nx)PbO>W2GL-<{L(3Gd9k)_FyXJV2 zGi<6i6|l*<&BTYcxzSbVCNUN@c(8 z0~2DiZ7^+T1WXtMGb-E-n)-Yt1)cChK;o7>Nx~Zb1By27Jf+Ym`|9kQvHLHNQBl~m z0W)Ue5w3_<kRvO+C!Z@r_n_{xUZjC4btgfml-V5Fj#vcMq=Iw2ZB{0zB@nK^3+8zx@S zS#zNh4_Zj}IcGt-Z1N%7JINGm3T|Aret2@XT0g*|zCF~|@0qJuh#EGCL5`SUhDqB; z1^Y2ZECF=F+^+)CHQW^k!YNhvr!eIBDzJrrzST*g2ltnCWDfdLi%MgLmM$b>nqdN| zQpGd@CZgnsV(nOg$pT@bCtecXu1N4(Anm$26vR4H%)pfy1h|3En0+o-`9)g*QBe{J zkF-Y00D&;op#+6s{Yun_ERr%aCHjLmru`;R80U#OJe)HIRWuj|oV9bbrmWtdDucxj z5j!;RVg`0W%6PdPB~Z*U0*eHR;dG-)_Ax`z#VQ&SSCx#&8I?SKG;p(oiQ}SpV^B5m z1BN2^E-jv^@`mC?kxrCQq_LQ;h(IfLAMK{6+b}$9S~u*cTf<^-1vCoxi_=@<2kGyX|zqaH$_Ep2GCA1_!qiDz_YdvM%l;7JY+%!y*N9&a&Uola56g5VgZc?*{Hr@|c_Vj5dog608lcyXEv&As1W4%?8`3egE* z4eRkhBw(cDAcbAGX%bmhmL~BP<|QV4%j{;fvdRT7OEpzT^U%h#p2J470xxm#)jfx>`f05pbw${_lkX4`+wbmU$Xh z$zNQ{sWiRO$bbH{oA8+XcW#5l#2{G`6Q=;QgOVlE6zQqlB*Gvy85n-Fc~Oq5$k?mc zd~Zt{Iz{-6w*QDHM_VbOAy|2;(X)-$0q(e|rMR^f0_++X2$yAY(5drq%+z(X)Ob=C zwgox%f6uMNvqMhog{)D*;`c2bfZ|h!RH0TMM_yM)(%vUM^7%*z71&5X#7A?Fa_ z#mLXOu2KVl5#eVA{1dcPE4EMXZh2bSRoJ{)TQ$Nh_Nor3$1NwS=#z;|B64_>i_TXm zCU#GpoNqNB3`0c%xhA87o`f(CE+g;mQ^R0#&G zRnYns*>@b69q_lTX9ca#amGYvr>>QpjA<(-s;*i#D>kaH`f4IC87h9vMg8QK;$9f@ ztz2|jDm#~q1C~y2k@i%XmFQU|H!xTVFk^RyFV%-* zLoisAUCph3Uptpi3o$5s=`EjmROu?2_HD3Gy>d2DG~ZDEuAPJ+uW0E4DDs7ozo{dSYox^#VqeuXmFxRlkC85s0*-43Ai_MIWyO2@?$tu)9ly?%UU~Per3ke{r{8e|E1jj z<~koY|NmxUuK$_;5552Y^E%i6ruhE__WxQc{GVX|&*I?!W}_Dac~Gn`;F=N;Es0bn z$+(O{ghI`QlR!bjMHB^tn!?SQa}#1fgROyE=9I*uupq>QWKoR}nNc7=tFIU}P!4&) zMzTVWJzX4%U3O$*%}y*o0(EI?vtuA0`L`Kt-vbn9R)x)R!3|ka2B9D!i&OG4;G`1o zBiw-)p$I{1Q+@OHC?;Scxl2okR4f)FJ+|zTx(m>qsXjBXFms3d)f{LfwVE)+{ERam z!`(t%{5zbIA{+&Vn;#-7&PzIF*(IidA591?;1zn?xZ|7o#4Q0|H|g>Ph=wW%4^O-0 zESLj&$uVyI6ccNIM_M1h`bD$H2$o}i{5x!jDpMH{%ru!+v0~;Jj6F6BWgv()C%P&z zG2tYgxO=T{J?+?wpl%dD#H7hv;EV~DeOSPx@!kTW4Kj`hVjd=Chjdz#Xn*IqS~DST zWsR~Y>)jV0IzTDx8{x$&OkaRttLpBCAT|@Ih>rE&-AHOv)g zTQ${8;pQ1tRGEAq7!)vKvzaTiKQm6)VMHcPoE;@rjz&g`m(ff}JT$OQic<@)iQ2BU z(xNHwx3`-1nY49c`2HC{F^g|tL`zumVHll=Y^g0}V(kl5Ktmb}nQ%7~DhXp*S{JCS zbuER|B#`h=wuv{fM>FLQ@y_s;qwxVXgJ{{GY3#%8Ny?X&4TL*g&_mHf%aLGXuyDL! zZ65e=JB!r;a!d^2{tf}N8hAuzLckbXNCn-(Qb3W+RggDt3A3+f(powHTKeX*#E&A% zR$UTeqgJ$*Tw@7NEeu+`hPz|~RKqw&B%C>0vO(F4qf(mG?J7boxj*PW>$dcG@szD} zCpqs>E4{~en8NL=OW{ih;}24X?UJDI$oKvoZBin{%NpA7ru#(EjmZb=1+jI9VyXN= z<+cvRY36#=0^ej-lPXhed@2Uh0`qf~3=8uUi>cMd&n39j^=oQMM}JoHNN>G7Qdd%O zo8j|Qku>l$$ZL(naaHyW>T6E|vR8V!GRs%RYi z#8bt?N42`iDo%-VMtv9o{0QI3a<^8Bkx{xmf5K^JU3PZRRmqn!e-s|uGcdS#U&~~? z6r>awhTOsoHqztOwX?jB0OOF+5{QuHUuJCZG0OabQ39dz2HTD0wp-6dw)s84vd?-l zH8qwQj%8&PSk?Vu`o=q63?=riz1I5`LYE^bEGr(9?Y1?`O?|ovZnooM1?<$y&qjwb zMjVOAg~yTKch!*8I0f!F@sj5tMucHUAiKYUS*xJ)`Bhoe+v4xwWt#ZGCM z9yeqN;4A?Wr%o7B3J#i1T~iDU6-gUF7WM0aU5!>x$`j1XFl=m^-s10gRD*EPx}iAy zhJj{^Ee2mzYHF%vWs ze;(~4eV0uoXJ_t#G3aJ}80EU`30Ob=)^J%p&!~w>)s#j8G%H`+tl&EF!;>rLcY#kN zG~lGdLO@uPG+oGJpRnFm0Li0A;k6;bwWFs9=r-UT)hAjib{63NqEr0dpS<7>1RMwW z#ReLw!2DWpd_wTaGLitaKEO2ST}jkWLu7bggf06YpD1lnWdPXUz= z4E@3x%|sjLKzYB8NQ3#^G2zc{%#kYGj35=Gta^1`XIwV%6dysGYAZuFW@mlAE<>N)64oAN6ixS)a=4 z{NmiOdkEKlabCXj%UoFVSJZx@^|no{L=NurV`$6yJ{A6@ep&ac=I5=dV zm23!s8N|S9+vL$`1?@tr9GMu8@P0{HE!~hQBL@)RMDTW)V(mo|*1`Qc0JCIh@lEJjsM=MVMF&WMEL9KKTGpd&2=A3saO z?+ib(^E639g=KHToR+?vF4vOmIVQ!Hma(3z6jrgV#G0m@TGr;Y*VtC+ZCAp^ZZZ)2 zJZn)NS&4wRvN+M_=uDQ(QaMwehffIeXb@fhYm-ITp< z)alq?FOd7k%da-J^doserjvons|7_|NOmo`FJjNrTA=KpI1VSfUktN|9;aS*9S34w zkpoyBrCvXLYX_d*c-(aokn#mH+r0cG&Ny$8CcqV}zVU9(?oV97e|EKOYVNNZ6Zac- z5k9aQfcO26>?2yfZf}uFC4TO0yv;~`U%$|PAasS=q9+?&$GRryfmn7T zTX)fyfh^ve1j(M<)|$9bm%PNgT1N|39$*7XQuEQu0mwL6mQ;XPk(0xd2~`yoXK{K9 z7&Av4(yS#j8$9CsHR}MAxv(*|tD%WmD|Dr44EaEGB_oV!0{Eh2MhjbO=`WNu?(XI- zBT?CQumxw%Gc}~Dx*6^RD@l9WREMKOtO8X)96-LfNgeQ@p!(B54d{*yCkGfvpq;8M zNHj%zIWphcuTi!fH93}H<);issWEYL>@#+uphKyl{c(y@&~P>yONXhhJWi3$9$tVX zbjH9gN~eMXqZZ-lyRb0+j%?|Uk$R5ooq_G^?JRx45U>6&*(X6g%Z`AKeN2C5CEQxw zI69i8PSP4J|2>-w>F6nXU8GS$k8n6KJl!t>Gj$VLY;0LGOL`nT@mRH(1vAVQtN2}1 zAlmm zzgT3rB_zFzBX0=0EfWeaLGlVu3>ixei{7M4;0(lWi&d|YH*=1VRbz=mo4a8hj%9a zK|-75log4EjWady#=V~sj1r33rBPq#SQIFSr(|c>blu#@02cgc37i$VW|1)An4r?g z1>r;kuoSVNnq>`rop7l07=VfUz8TD7T!veXa3a~PXw8fE%y-)_a3RK+u+bQD#XXw` zwF{@CM&^$SBTHHq0U(uCMF^L~((&*@-IjS{k(!z9L>JA>6-?AFS*R@E(^>37B6Y}; zWPeBblLc{`aU+XVltQ8sK$;9R?#v8Hy^;td5~rtd4)yRyeiQGurPzk0fpmzB^Kfos zTuzn~2t43ILNsZl=cHSiYb3dQ4rJ#v*+mx=rb2q$KU~gcba2j0)iNlWMI+8O3?aE& zb2{v@XZ4&xW12KFgQko~LCKo&rtEElbGa;aY-o&1h!Q2c>eNZtT=Wjsc=qP~ zIP7lfHJtG-i8^+qHdidIOCtBXuf!qn#KSP}nP$BK2@=OHpXzC<`A6zTb>HbtDt7zX(O$8| zzGch{s#*QP(|RMtqTqovRdu-!E~G}$G_)yWJMzFmR17AE3tFeH;nI2&^cO1pz0D>> zNrycqH$+oKAM`~vnQ0(HgZ{`B>A!!dgHMPQyl8{>q!Kq}G@gheTG&v9V=f2L0iLqIUo8@;erVks?s3J)j9o4+*FiBnU$!Fdm;8Rrk55~0^H@qmyvwxDco~>pVjtL81 z(sE(XjXrQLY&^18v+r#An!S=t9_rzF%U*6zaiPiIxWnho-?LVv2Hlr*S~ZA$cAFJ+ z#`xhmcHbgnxjLzfXevXEYU1hs!ZPr@diNYQ%Ak_YqXhq@Has-xa@1+zCy(C~N0M!l z=Nn5f^gYfyJWuFT>f@r7-%TUg!-oJIJ8!mMq5Bpdk}g6$A3;AUw3ZHE%6a@uq4!Wy zhEdh1wD&O9GO=*!mp)S4w)Ct!qTRN`HGCXXkXK=Y!R}PG^7A(OUM|+YINFjX=8^)w zwn{AnC4T*V?9b`g0;{+TQj>KIQcyq4=OF(G&d_s1wjqoMDrIJ2D`Vzp7r))^>VqK#gd6zxall>*+Q=e=`MsnFxMRZ0AwJ%SiLJeDpcuCC*6^j4359;_{6sch*ZI;e6fz$AKcU zHXKmsxME)lD+M)_N%FtNNR(1rRcr{$NPjM?2Uj>NHf*p|XR4sR>{h)LqHnO&kepV% zyp!IbsrW(vO#D}R?N_<)W2K5mozHVx$IG(5sT5a!-DPpzhAg}Li;JLyO1l~q!dCeU zy}|cuqiu;}79oOjWdkSub;dFL3vwg!-~0!o^i8B+zF+G}4bn*NrSzBK$FfQdELsIq z>Y6kyeTh{&15?20)q3%4=aWt6QB}#mq-6S=!07F-pV}cM{#kitb)_Azdt|d7g@H~+iu8JZx((x>|?F( z1lxDSE>L+(mR8?OXAfp@bLegpX}HlV)3;aJWIaf_EXmv4;`3u(MUr&s4HDkw*;)5y>L* zg?t0a62@Nh$FtpJI$UalxWu}?j%}4U$8WcG@-lutuK(RQ(N0T){MvHB5tVgk>L)Pi z(l|-BT6;p+XDA!s+&&>=l-RjG(+O4yGioA(32#v~k{wSGYcj5Xor$`ddVAl-880u4 zj|JHsn~WIuCtol^@3Z>Y=Eq5W+dK8fH?OcdD-=*_Xfw9`an692)}VSO5qs)QXI^1? z5-GIu)nb{1Q6?)vF!I+08LfruntGt2f&wLe(jP zV!C;MKyKG|R{L$MDDus}#aL{(`{>~d)6wSI=$l3TS?y$x{8Go?!|uwVprm@^j~_%3 zM2uZ_{@CvAFcsuHjQb^=_89H-1aA8p?7xVeh@|c1CVd~PKl_rj?OwS1;&UQWyO&#e z5ChpYZryfH+kMIE3_ia6%sWnjyBEWEC^EPob=oQNu?iBdMizRR`+ZILSeC-)#yG5c zN8={v@dx>8P40&piqo1+vF<;9FJ#TNw0TNYgwyLwzsOroZv4ZirC}zFPGy!~Ufth3ns)_TU-h1i z?jOIp+$AM76cz98f-xcazdo8!^(I|?g#7%QW!U}Uw%ZzwANu!( znO=LxSazph{!Zrp&3gN2^R}~P@W*Ohs`qerxch@x_inJ|rzMu%2LJ*b7a>LnpdSu2 zg-H}WGO%B^Cdxx3ng?4GVkhAVk}QbV?cy{d36BOK?04Z{qQzs;y6Oq}YGJ0zP`aTE z2~vTQ#r8Sty9D`gGlz>cZj)zZ*~y0Jc+SYFjUWZ%rJxLdkkv=hWoUE6&y`@KT=_5@ zJ4~#P79{Gd+F~9x29{YEmkmEtq)$Ea#%;VZwX}aJHf_~Bzdmk+s^>RQ@qpeS#i)YTR`L=l*JUDY>XbbIEXvHLnuGoIrRP*_? zb~*EQv7`YF`4{X8UZ-1L@zF>`D>KNq(1_=<+>iLNKJp^*A6onV&guEozI=8)q7l1t zW^XXBfS~`AvbjEBvyJ@y3T=uysxy3ZI?76*8updE89`WZ@-}x5hp1AV;`F7h} zpA9;=3bz=m51ovAfbV^Pb!)@>3nsjQSbNnWewWV}FA}#jz?K%%N>f~c`b{Q4huZ5X z{;2&cA9cBsA|H*EQc@AD{VHk?HmFu-!#unYoVf6jDLH#jo&)j~8y4}pwAEhz+DOvr zX3+J!^aihKdq#syhi8l}bCN*>o%J2IpvLcg{Mn>}mA~bjnh2px*{ z3{34+_QayC?whyx3lG%xBrxE8tD1_emI6*;^|Ef8MsrBVpXG$8UadN?V3q;vjjrvv zN?CV6>-_QoGNl|oHPVuDDqWVIE?Cv9j%%@NQLDQJ9Oj@mYnS4rkg^?y2;(+%u-(Fo zX?M|9u`iaFG_86sun0DM57J2+&heE^p?h^%b`do>-X=m`{oJ*ZZilC(ymOclBPD2iI_;3Pe>!ox zamjKdxB5K!lu*L7=Gk$>hq(2JBW%fIhsg%6v+wr z>f-m`_L2Qg7Ki4=UW@%Je~ml`@@v1p$LoL6wXSMpw-8?}V##1_rGQmR($%lES6%Hv z=0PSzE=iK%QNhv4PSd%Tx+KdQdmA8rsspS)0n-vXDe$pC}_M0<|3U-zMx%FE{ z-$kvpTej&p)gD(=4N)kfE7Ds*GBmoTt7N$378^>778RxzBmEPRXx1Jn`ZfsC7rwJg zd6LAk&fg)bgEl2bPQiyq2X6%RcCt?r>VhJW zUyF!xfhO4ncp=YkLoy${ojiAWhv@G0{veYvMW#kyil{9Kn%xsnY)>dN%}cWbyCz4ZPOz#?bFJ6sHu@rGew%JdrOGh6q0=pa21yw6+Fza z5OJ3F9GCkbbjmszjmE7w3})cQ%MSad9{E8<@1BkhA_bt_*ZA1ySfP1^nREjPWst{b zB3j1vbk{blj>Iu0?#9d-#6P#3KHe&PR90YUECIoSN`CSSTbRuX8A~1!O0#{$2+N2_$Y63 zdvvQJ<%NwO8qp7+oLnBwk5|QvIObqC@>n>LQ0&32;WngZA+g3pQpbNWD+h7gxU0 zMLMHzKaU?BAG6>srikHzOgB=&g1J(?;7PwpPf$fWR&%fx)LqwLi)($BWDwg#zoh26 zY{!ONlYYNP#>X6IkX2pOcy$nAAkPT3EzW9^NkS8j0h>YBo$%&^vgW$UUth zYv0(waMVKT_`dLcRTtfJ0us>as{Nf}6X7qD4e#e$p(QoDP9Hk93vJNEn?qCwRz_XmdGMU~RefFX- zs)9}5-ZS>-5z=l?G+~)aEsw7Tl^k8HySjcsW7C1M9ND)fnLfUR5q)Ep$XZUj{+`jV zmx&xqon&w0`96x6lz+r;O%6)n!B_E4$nxl07L6j-EWtU2HSzkl*mM24W!085>!}AG z)8{$30pTL@53XB1DeWU+ib^re$4wN8BlhoenQ0!V~bB}H-73DLvR03h(P*kn|y0FsQCc~iT#agSE zF}Z>)Hmc9mZmgg9SdJIBJ!3F$WkpF{ll?4qGv6@Y?5VtBYH#C%xdTXd9ZFNNyXvVP zcUMSxRnYDFu8l8pHiLs~hu@W@)92gkH3WVqL2PQP`FZd;Q02!pPiB7vT~Fq2+&Q~U z<wB`4efH4_UC4R4d0uhLBRLs76_%+QHP$-x z;Y&SZomBRI3!E1kHEJXensnU+FLh(NN0Yr~fqLY=zqFQKw6xag_k6n&mT7ppY0Z0$ z?R07xUfJ<2-BU6yzUdqcI{Qc(elkNf^~cI%?(0YK-_yb+Jw=p&Pdudd%36uw-tAl8 z(jWeOS_LB4^?M&Y;x9kUmVR_BdS!pU*|mTC?Qz5ON5t!bt^DH2X!7~vq1wj@LS9v3 zPVSbTiQm0d$UH@e!kU2GCU{ZEPtHzJDuvRIxEOslc+~e7qKAfk9l;&4#9SbBE`=}s zG*GD^2HX z{eZ@genZ-i+}L80j3NfCeU0o*x`ho@_ydhP1M>#GitGbCAii*79*rjn$Zu+cdkKS= zK^ky)l80Coe^CD!D#G%GcQc?9>Q&DG8FHW6pP zNjKxk@rTDy1{(}DUJV|~g8dXks+5XAvhlcq@EOQ$tm*@XBH%2AVF}%)CC!h9vco*; z@LA~T?ug(+cd072c15GA@N}vE{J|pwsY2`abmA7CFC!9g!{;WF=2pBI7PSfi()#Hm z(N>Z|P>^#xsiZ*5t7ZfuWaP+&kJY*q-DQ+au9elH^$6P9CDFQMJZi7apy)1R@6cv1 z&Tk-$UPLZ+={IEdbtpPOdNXE-CUzt`MCv?D(i|o!6wIT$H{7=Ku`@un5E66rDMB8v z?A|5jkXyDXwgn@)e<%V>`7oB1)0B5DNU9_!Au0FyOYD)&U{m_oeICg9P5Oc_U!ev< z^d{TyHG$eXPL?kx;NKd7B?f}eQ)r_K zA)T!*JlIF|-67w)-IAvy?G#-XL1d$S)OcA!NO%&4Q&Z_|T`kp}Qpu7zjb|hxlJz~B zaY{lhHImCTA>XE1%<#<(Qp`yNrq;WP)|w=@_`aJ_HkwQ?x=g>y5Kt@2?VAy^NX_sJ zDwA#I;5PS4LX-{El%v8^D@f32aYWID2`b-|D*sN8A1Wu`C>No$M)>sk9f@Y?%3;mT= zi?Sgkf*`hl)rLGB!F({a`0QmaEgNl%R(NA~m@cHDi9AZzwywEDuG1(EB(ByItfYsp zLYu?Zcy3gS*F{I3q=5WY@3WwuR%91>^rV)*US)t@4y@keU(FaR$yOte4DgoQmD-!wy1_V+6GIS#!!KLt;Bs)vOh@F>;}A${ps{d1j0D2VczWYRgNmjxBaAyEO-xWneX9c7|FndH5?hw-r|Dvz^JAXl!3F&L1;pe%jR}(|HFgbmldLa$ zo#2}7?~?-;OHc1X(wJS`S3B+|rnu@HMjh(vSL>27`%uWff_SY_?>>)QTNIojFaDx} zORX`nlrai8OKN|Zryfz16Zw}Z7qGDqD0Qf0X5qdMmNGpu+$&+`S)tzVGH=hNHwv~e zJ3%#DR0y2mY@*=m`)qQ^qYPEX(}H*(g7?fGwN0^j4-B0Sr3FE5G+L&l^Yuh{RcmG;?%m6@l?#X&yuT_IS1Uu-MNQv#pj!PD>Iel5@K=@f!#blh!RBFmj`FW6l^Tq@q5v-e+AwpH4TiLRtUqRKAZ zf7@M8S-G`!jObs&YA;8ikS7=0%3dq>FIT)Z{p>oBd-EZJJ zqdj3lu|5CPs`hj+zcPJ8G3&UK-eWn|V`+=BBxF7FcoRc!(eukX>-vha0A=yx@x^ry zy|2@N;LX~oMH<{i<jP!{gD3J=l0`7@tq^R{*M)1QO~0v z4kD%TF=pCc&M)>ZG&i;!=zWwiW@#7)^+_(CF+Wn7EdQM@F-ISKhvm{h;gXf=r0IYW z9%HtWCZ=rJub6sDM&L3_g%utn{TJhK6#uZ4^svQQ9CzD=kMTy+>yC_0y%fuwkX7az zw=?~pyJv=hWnO1(Sr=nT7e0R1VH>wh)Y}I(msvqe25=Q;jBFUjQ7Qh>4c+m3IE(kf zV^+BCAFXkhXlR2B>zuobEXo(nNPrV}(uOL%zPqlWxk?#O_d9Zg3 zwTull2|g@`de9bHxGU%;tB*f33`@L|Vl6o~*OXLIlK-ae`Tm2Hq^u=_;c=R|`*He- zqS1M&+{CK7UYw0vD>VHSdw6Fjz+U~yN=AXbOZpRrEr;{TrNu4a%ZM?p`!}Z(kn;m9 z@-{yHV~;N?0B)GA#Kz0ZLv#38wQ9r)+Rfpsf2yv3>i2x2F?u=w?-;}P8<=}{^YP!1 zljJWat4iKsn%-fa(_g=w$GSvYIz5+^oW6^@@``)n)&Ip{{&Pno=9Jg!Y{&C!T8*RS zFDH1+6PQm;N9@tz9nrP5vYF45W9)JM>4*HY-kj6ld3K_2X0XpMmb&j(Kl{e1zUbr_ zjhIj9sQ9uETZWXr;BQ&E7i;O1et!4C_c=!;*C@d<_tiK$!9xF+-<$8drsJu`$EC(A zhEj*Hnz@fXR!)toB2b0aG|#P0tJ8t2zcmBzhRMDZ{Qe*^C6jBRIpp(4|95HrrxIU9 z84sVY*`G@D)UeY0;)-^ks~mer)zYRvJ=eT_YE)~*PL@%8@mlyEy`ZR)d!tft^M0G! zYue;%o;rPcidCr9cU=psLkq9{JPlIY<N{(!br)g1ki#t1T#Ow9sW9zJ-m35c3^& zeu%3uYJwcyA`0b>6-%OWDUR-MZaKUNF_U|Fd;}FpyezC>zo{pUDP?gaST1BD2wbVn z*my4Gny(%>#|pZg%ACY&T)W_oD1s63mg$smM`%WV_l%f7_G*6%`om79#{inl#TnPH z+Xk%Kn=>DQN%y%4BaF3ayoM~02ZgquT2tms+}hQK@1`>*Rjv~2``S!lh1QQvMt)Ih zX(i@Q{9Qv)X5i@~Z}DsT%+}sxU7xI|hj6!sWk=KO*H1FFA+0yQs(&~D#ET>wZ95`T zmG2F{kJ$YTtQ$1iAbIr@zIshpWj`+X2fR`)sjK{0C;4k1EW>=eoyPx#9bDNSTl zM}-*ULCvqe_(3fs5X%3<+*^OO8LsQP!Ga|rxE6OO1gA8(yOiQy+-ZSAOK}MhoC2k| zyK9R}a4lZEcyZcNIn24&+GowRWvo5MIcJ>z;QQtM#&bXS`(D@f?0&&?GQkx;F&+Eg zKB$V_pj_>y8%6zjMG{p_J=rr#gjbbGU%zez9aXnxRlp`N0bsy8E7F zr02A1-SHOB@CA*^@|d@+2Md~%FdnZc$-pXE0%p**3+FQ<6-MVbA_ia+mPJ##NtN^3J+ce<-m9g)+RmNuiuS|b@G zkC-}^HWX8~(+GBH^A{ek2cX4)s)mRYC3BK5s%#!%dl$mzwBuKb1Ifm1!JiA&sobN2 zxo(3e3YLVVztfiAezf%~zv*wTG<}B2xcn^B`Oy22=C(e@Rg!JL!=jyjRm@VO`l`-7 zlE8moRH{5fr2X_>)`$WS1J-O3GWbl&@=U%@*Ex1L#?!I@% z#d~pF^((0L3;q3~8uLP0Pz*)9J#nj#u1U|-yv0+bGn5DM}Us7<$SoWb4Psx zYgp;1zH$JzNjIY0S1<-%qMhhhTVu3N?*?w^zfHtB_{}K76tG_06;w8cU-(^SQ%+G? zvg!!dr*rlBl>D~odj5vE{hLx73r+M1U+~4~0+yh6P;Q#;BL6$9YkG!zPBuz8!hDOL2?G+@cz z`4j^Z*4$}D)!{RTjD6*JiIxN9CK|qUW2u#b7DyIUxcKZKe)N@nP+Mk$2!GqN=vy{! zlN4bk>tvN-Sjj*xF4rQCiozcASGuq?Xsm#8`Sg9sFWh*cLoSBVl@I%_S83kR4wZ*@ z6Rhx)^v%6)LDe5D=!ZWZBr-&`{Z7sSUIr_3u-Bnsk;_C$7|jjI@yt!hJqzzCxB@MW zao#BJUruJ|<=ao9_1T@^{gOUx0m>Do5ZQeD*x_ipnivtKklrG#t$%3z2P}F zpkReBB+qyB1GPl#>{OWBbc#U0gsOcL(`48dxx@| z=MEpEGEV!(6pz`TpV()Ykk3;+Q#RBz<#BCvvuQCQ@5$j~ldn*m%`-_~Csi@5ZV|Pj zG9`#{a~pRwNL}bQv9j8v3hsHoaJIET)9b1Cd&pYk=f06k^2RB3V^!5q)`D`s3xBgq zXKG~0`pUYkxrnzP*V)N*;5kTu&q~toc79`(6=Xg^)rH#rBxUj;7~kz4ArkmUjiv^S z5kuGb6&F)_?4^;wUWS-BH1t{E#aq|C`<}%);Nz8v2(Ad%epEIl^UB+&B;+5RGb7@55J&n6~UkDTg7ViYCn|saO3>t6e?o@t=YQVV)^@#$?y5bx6CMbWh zTPfLHt@Y?dG7k%;@9%M+=?gNMe+me^wm0DlS?K;<_bvm&etb~bb;zY&B7>a@Bu4C$ z>rgGxPpdHQLsq}5H~8$B@c?w@&@dU=ze32Z#KR4;1zOKE<0_e)gnFJ2Vb2&Z&zV@+ z(hEa!W^q%*jzAbCZd9-&2}T-cm+Xr2vl4xiX261`xzRZlOg>G()Iqwv##O8RBSoX7 z@o(=49?{-~z>O>{F54P5%=`r@(bAKuQ;Xa5J|$CAr{(y{atFoR1!00~EWTcymlWg+ z<@z?K>*}IamB|AuXYOYT3(sGAU(|GV5+6VNY>kn+x$x@VsLZXfrxkMFfEZPGiMdK{ zQ~bP=!(ntmFxPMF=epHg80W?F8dUbWY$xle|Kj(n;TN&h3qdJ%vyZ$~`FUP7Na?3J zFT~WfC*l_0`%~-7a7?xotglGldtSX#LNui<9b|amUcVBVp$+yw%$6$f$U=ce_NFS| z>+P9Y)cbLLGah--SZnjA{xR>cb$fSKmQ1kaOeML+>C;!G>h$SDQk32Yc9I`&USTYD zuD=2XZ`a@5x|vE-2J~2sXB&JX9=qp@EC0i{d%d5w+NJHp^_^bDFqB&OSS+df$4eHflf%k=r9~oZ5 zy5E$FztO!oH}?qsU0c~smv(g@)!Ie>c=Cln?TW|ivP8qI!FEr{AzN=bNRN?chn8gkZeX_|3Sj51+kln z_Ap|XF?28$t515tdIuH9SRms+=iGmyuB)bnFsJ63CaW<|;;=MgYptBHD@k!;a4>aD z0lazTHZ@yQyQAn=z)2nqPU&u_Yc=6(V6;UYDw3^s13fK|&mD$05rdD4!6?&fugfa0 zD+ll%{I1$<%X1>sc}fWF`i)|Znyw`LwnqpJpGL*bfV6<|U<|=I{ODF}!7V&ZE?~6) z?)e3NSUrwyJ(kW%Nr>aTPV78N9$J@~c8~{w9gG*CR?ooE5n<$WRHDGg_Z7M93;$k)7vMCuvO}8OV>aDJqquYnMs*(z}Vh ztGvAbj1f@^+)-)PQi7*DF=^Ju;;40qNmZ-Lgi^DTBB%*pv!RsarX$yrmdUVkr=&HGggq}RAn0R#Isi)2@p2R+ubVV{FLVvMlKrGL2 zp|m@OCp8;r^??WzV;hR1~1W9K+v1}sSvw5+PwHl$a`7KDS-CnmXYlCive#m;JG|lLIj?Ex#Gf^|bivc+ zVc_$2aHU%<6)Png>!x;ll6M<9(SF|)GAO*nZ=SZ}kuQ5vOZa1U#{_x2OvzBN8+g}F=# zl4_NNxPH=`|1}4=Z%7e?ZHZQdi6+xE;w=5)We~e?_?r^@qoU68Si?Lrp{6mb$|t@2 zs;FuR`|5;2GImai=e3n?iGbiLM#=|Fo@Y{x1;LFKEJ-D*o~zh|b++DSEsYzEC8CW= zKI~WZj~mZ+Uj=rTJwa4j!WSB!vbN~t)vH%Sj(8#g(8mOxD@c%o~`tR-E4iwh1b zp6@-LK2-4BtbH!i>FYdm^+7qMooJpMO4_XI8#*_iGwiFZ%8hzSkPf_{l(?X%^{psv zYOCf5=^STJM=z_7z4j--m-_lvHa1REomAskO7l1?5M-&vJ)u>}8b~J7Qrc9J`n~-6 zN^>G#Yd}_l*(@VAJ?MFghHkui^{~3zP)+HXH+mx^rCZx8Nh3|LIa)}?wOv2;o`!6E zldvv~?4I^U%)qzRkVi1`tX=))sfMAl#za@-HCWqgzl<|X`;1ac0}%};rMr2f>3hfM z=feo^C@}bBe0^T10mUVu)=10OcYmht{!C9KTP<1S*{qcMO}n~#fWBX^hMuxU+Q8o! z%&4@-rfMiuMItTNL+5hGT5)GyDPmEXg{pM#y*aB|_}-ujub7!cRg_yff3PALN-;F6 zPKPx4URUCa7%ehzR7y_7o~Ob4{>FhHJLzi@I;RN+SbEo$mPgl%s#GqD58%gG&*1R* z-P>1$;tD*ndtp~CYO^YG=a5e65PNKINbtUSj#kt)>ZIM#@RUE@+VPg+#_z(3N9g%& zu;4M?`{o_%D^iQ}LI*-WONzSIBT_5TFrmuWyoFQPm~nn=w#(QsR9z#Vf7H@P-hrst zYH_!lfX}*ew=$N`n2^ZBNY+-^-hpV)^)rs8&r63^d|T1;iVOOW73rn0k%2n~n}T;< ziBz(bJmR*6-sSc_AR(VpL*f%Ms|+4Tn2^(X6H&q=p|jh9mNMPVO!vxYev#^UZ6@FE6Ll4U!lX6?KWP zbpyr>y5Igr52dE655}&VoA17Z?woGM=suYI3J%0L{Ea2@} zHC9F|(bN0Too?a_h~JWWAmyCuT?X{KR7A;E1nKXWOO~&xG`(EDFJ?r4jA$i`{^95E z^^)ps5YG?UJCSJRmry>2`Vqx|)cT%s4(q;8(45!yQq`mKpl$2e5X(UuN+GH4-i{Z) zY{$GCwIq9o6G@FPA*8aoq&5DuGS=@YvIdOu`kWNN5P1{u#&|ApY6saa5p~9v1R9GH zUw9_L^ejLUQ9FRDdO|PHLQxX zgi{~(JAwCNsL$f|IeqqeRy5Kzt8X;Zf+W6MKf65jr&}rI%cIs(ea@DS^7B1%AF2POEV=GEgXg-{daKtpwYnNHW3NUZh<9yHB9C zL4m~^bYZ#Tud|f~n28U#2_Tyl7?kw}TvcDDh+D9duDmjWVkRm#L718>ZJHF?qSK1) z%*rajW#u9zhVE7?ZLBojmYay4g8EXspB0jC>O5B@P;G2KUzTpu%-$1V(-H~9mDg*q z)FHF5X&*HdiOnRUH~=J=aT3x21Dd)LWP4#@2FaMd zX_GQ8S0c|*dNIXO&VYVxN-UcXS?4zkq z+6gn;&N0xmx4F~ulhnAYT>Yo}(e9p=AaE~W7ZQRd0vuoi279|0`lUsI(j|CS_UItB#ewEw zM%iK8a=f57?O_bVtN9%WGiYdDdTwveCe5iJd?%2=dIe0x(MEM=e!-U(!p6%TQ^%BPH~!4 zJpc9!r+e*cO1g9|@~;2aMKj~fKuMqa+Umry+{Gh@K>oi&WvYkZeK+N2Oasg%bSD&^e8G|#r*V`a@ z%cGm?{eTTfm;0~xR-)=lxYD~Xc@7s>iy-gw$9@-&TYZ?z`!MmyYs##2-#nmYy>Z~- zOM=@s00;t1HLXEa4CEwT|#%*x76R1M}vuzdNTNG0h_OL5!>U zoBiKb7>@E}SAJ!jn&q$3->kmJ8OwdM@t)-ieb|P@!bbPEF)IXkb7HN_z5kx)^w;{P zOc%j>!_6GkFL|b$+i#Cem(Q^5;E(j%vy&Err`8{TUjKMM9o&Tt*!x1)xb}%>!6^5_5chlY2p!J3CUy@FP zVnK}S(|-jRDt2>W_r%J3XdW>`TJXnFmwh z;S|cE+T3AKxsgze02+FsIJxoZEzce+vA8sl4Ms?tjS%(d&Qs?zKiRmJ@F*oxf<(M*<6y^d@V+4`%1z1c2NG}fL&=51;b*>y=8Zxq9Rl0-t!HrwVweKM91*Iz`Xo#|}xNDygM&pinAiSE1radhnX*-{_3{E4Al-DTg zv$Gb?L9)+rp=6by#PRGt#W)d>O*iT6{_uW24pB)AvN9yWc~Z7Ho5qSm-} z(jgq4A{LKPkHGLQTfP)?PwPi@}G@Yc%@msmzp^jG~{-I=MAM(R= zBD+67_1qT<*9wzfEbGtPI4m7kGoh-l7n1xr9C{MRSlHW_H(OUI zxFG?TXK721Jhw7Am(~cqtnZp0E647&?pz#Ua|Q7cuvwSc(DA8z+Y={ZQ7uW<^J3H7 z7WshKuLNXs1VDL(b!dv1?PSza%R_ze7eX|S_vcAJW1l2QP|AlsIvIdqR`KSIUeYI+ zPnC-2L&>VCVmJ=!!7HQ<1mmMc*vRWSlZ|M2YVGL1si!#Vh)KQ8bIsz@YwQ=6juZF% z!N#PBDb!P#dWaLbFfcR@>;lB7ju4LM zt>otS*ZC zG?BNnUo=#h>+DT5(kn;exBO@8EzB^KSSz>Nl!PK}Uxx9xZM-eew3vIj7Nd<#Mbk78 zd17~;wPlPR%`o*(NEml=fw%)}nL^w=EUa6aJ$Civ@*(+dIc{`%^*h8d_1aa`W@8$l zsVDW!oMphg2QJG%$m{I88S$Y3t;r(ywY>jT?FR z4IrlVNkp(7u*I1}#00dU&7HSJ$QVjWS!Gy&b;4Ip?xIYX{1(IJsk09#R?mOYBNWPh^L%bvJriTywFErGN1CCnE*Jo0+7@?XTux5 z5nq6%+KCYg%SJwD8SOb>lz0!~kmqa!y2ES-aJhfXFZm7)O?=hQ?>A-?qU8d1S&t+9 z>JBudTozC?aH@W#^mjK6Rf1bHe2S{(uY&k!j1>F*by~yl%2rP6tP}0Z&4seGs7TX2 z&wVL8BAcz7?lKH^kdbhy)Fm6iAM1luy*YjE!&~|v&c84dR^J7(mJ@x|0!9t3C?H=2ZL*`|Hg<5( zbE&_DaH8B$Z0CtFBshq$f3jB-e zv9UTyKGkZF^a;hE0ubWhFhZIyQkAd(E*XN(a}>W?0}0hM#K!mvw!N>m?>R5;|=NTMvtg7>x=rg7RlNa0k!eW$5lGPePb6MfYOW zw)ihZbWHy%@g8AoK=M=**Y`ECVmHPKikVZgFXBz`U(ZcPC+oZ$S@neLwx?wyT@rM9 z5#{y~y@l(n6{9uXyfUvWBzxw_=H#_Rex^FEa-!uvuGJB4|C$j*3PT5l;?M1Fcl56d z5$oezGc`Q1!;9C8j z3gddI6}>`&x~8KAT0WJuYiIo*WN5iZ&zg<>ZhqtQ0`>2&ABZmE=xq65}!Ep?Rp(9lLQ>ArJGwI2{?egZ9GDUw({vtcBh+$0-NGTs8SV zShy5R8lLiavLGl>5q1ui^AbjzlQM_#|44H72Ubo5b~uoAs9{{;5;n^h+&sp@0C<3g zUK70I^vq&>YZa=5Pm>)!?LI;38*?Nsn1y2iHtsKY?Vd)DC6|}Dbl~JUAW6nDi~y6L zsH&mI_gg~~zGrU*dW_b$iIYOI#-GK*b(Tk|Z3P{W+xZ61i#Z+ukv&Pv!)nvfJ7JC+ z!$xu?#z;*Fuaa;5GyxW(A;~&#SsSPtBMcn3emvCDCP(Z2`H5ychf@0Fi)__i>jc3c zLp#@NU`8MK6zc-bpyXNDvs}mlQYhp6fec(8F8a{SsNWsquStE6m=Pr73V=|LJB16q z?RehmkX5`Z{J{6*Q_T!nQ`&6ojZ!P46AGO^n3Zt@PK(37nvtB69M*Uk%Qn^ZQwQgqjp3j{^tZ1A!qRM3>pGoGJ zn@vJf$(ml5%Tda6Z_=R-yR?rdLTx?c(?}^yE%5Gvc3~^g?8- zcq~lNOH)kyh?I=tOuH5}aZy_CG2+wAI-dRBFhYY>GS=OC9%^WWTET*PzC#OarQ}24 z2L)@mM@5;8b)((o>zpI+Xxucnl;?_uYCYmQm1R_@8v-8}x-+HnreXaKcgHY4Tcp11 zHH*;|BdJ2Dh}$23s%H?J1bdron^&0t4HQCl3EqtteJd;q{%I}&paCL7s zdkk$Z6*}6~iLSZ?_1W#`c8pw1t8|pgx&=yT2>iZM5?fW{*yDhtkcc;NdN3)hJXaGEV-BU4CfLyS9lJ?Hd zC~MsjW$z(Jl1IkmTBKj~3fnH->7AALGq;mYfku(TcZDZe;9m5>6TNZ}7Mo`)L@Ti6 z#pURFtT5A98&~bpZ>iEdJO2-z|lLWXNWvsdCzdaH+0ZWrS-MVEevW8 z6I`V2^&E+oW1y8DSvNdYg(aFPUAZ#NFgZWnJ*2O+_!5EfYx&n1wVIG6OjxkDRIo2V zUgKz-0QOSvT7M*f4WUWGrQ}(+-tXb>10k@37uZcxBc(zh__OKM-7~!SaJsOyT{8HF74^ehKTCEbTHSGLZ5SK6M%Uk|K@brnNo$8m(uZdN zaa0~pA7H>=eEsV4Sa#-Ei6qI5t^G<7`9VvM*Ol?N%A1d$mU%PUdT%>AwXGnWgx1&EE*e$Y=ypWtDF z^7^uB0MYRkGN-$*0QNXXod6Yjp}g7R9SV3%ox<+)r8eh1YfnHprtOZjj2(RWtBi~i zYy(O)Jp@=OMHC)aMY~M0MQ?!QN$#xl))Y+6YRMoWXL^7GSm`@}wr579k)chFn{!3` z3;mtI#gJ{yAo>Vkd^QX2zGBtPdCJwYhvRoVb%i2 zIaj5TpN{A_LjClxy47}~=7itPushT*wK_mtDsx>0ryGXGFmcAGIWMg_=-hU2uo)w;ZE=7h z(+km(5jrMaH5=w~jvp%PiK1|@Huqnleu`pYch4Z*i5eM*$*`fp#8ckF6S+=3$56n5 za5NU1EnY}jm&AT8zE_!=M|4Wm?NiLjAGQS%;enp}&adp&Icm2!juQM(i@#Llne754 zpuA$b-B_nxZzgH}7On6yU*3ku;t{oUpY;-zB+;EHm>@iH>gr$zB*D(ZoO&jLA!i`Q zD@IkDn$f=`1xF(elDn+u>^;u4hacM~xLvF01+c%7+CVzbyn+3fqlIC@UtLA8@Gi$L z^@#X6&(*%w>1B;nt?h0rFvf{AxDi*btxo=e>+AUt^bNB*c-E&D0>^kpy_g(-?l+3= zA7L(RZ}W+eesq~n9F9dX-)aLKY>6emGCS8b4!jP_`sDhYjqp#dJ5=w= z+q>lT>Uivqg7Hqsp{Txzp~_mT5ceW+E?dZksr~H_H~uBI@g=P5SbG6^H6Hc`caZ+1 z=-k|6Ti0$6$0JwfEiEd=LTQjT7n^%W00#({AB%L}=8T+1qCiw{vyH33`PCj(LHRdw z?5~KLKg)7gz#U1SQ_PikExtxBQp{(9{ja%BFWuO?HAA6Hr_sV%sN5YO?0|t9m-Ar} z37+gYDFZ$u)&cb#;M86Ub4LmIiOIXo$PMy?pMz%4%uYj`SMf|uD(i^&29z2BAyq2y zGh)0@IeskZ6OIDlu#B~K8h)A%4q(&NBi&`8+K6Z1iGE;Ak4fiqZwU5@BIeQ-i)#R4 zWtS6E3$XhRjt9qYNiHDxp#jg~ivDppvO36LP%H3kXiF;(UD_`$%qhfw^YLAjj78dK zF5VDdC^cRbn5UG4y-b0tZ$?Td-mDDsvHlP7uy4YBF@SL#f;?TbJ-LgXbDX+hOMZhY zk6US79npnOwtgj_yxrfnR+s5KJXoZhWF_v{8sIpU`lf{PQf-XnmU+9#D-<+OapK{l z^lTg-%dItH22Q0q>oX1zZk~Xx%phTt&wSVzuN@wi$v6~COoc&s1wh9Cc?SPyRQ+dw z6&98F4^Voce>DdEKTEm%53yT73C;-nC&=>OoJ0S6M*TnY_J4xZ!~S(!@NaS>*uO*b z|4VYC|FaA}|1TL_nR%;8j#c3STaURFE+b2lsxxF@BB5u*$xQ<)z`~E-cu}4+@er%) z5H{sG$Wkn>@B@1o9%$$a6^gcnk^qEJ%LIZv=}i?Xs8y;t7Rn z15Ld<&f}5-Wvl#63GO2{G?Dq9cF|ANuwGNi^7BmRm&$gT-QZx2tVx1c`gS`Ywq*k! zA#swkjS04S2q~VhN{X2h{1l_Gfg_Ms6st3~RYA|xY%aGHQ)kHeAU8p3R%22ilqyn~ z*HNsd$}AqQGGWA-T10cVQiwCLi%=NI)Z_DbC`@u`3XJ7SbzC3Dvh=VI43B57>gQp@ zL)xlrmP6E~4*Dydk3N>y7KR+N2ox4Ai-S|4dvbyr-aoszeRYPFbSFnlXiBX+#VH~= zUFW3Atiw7f+vYXT?piOOx^w^% z;mQ0t+PuR>DlM`XETX6z_GfEM)ea@9s%NW~f>T52yTyrj$(Pu}%}hvL&iR0i7oQDf z<^hSAR2;=-X48-nU^%eRZd?0Dsq2$XA54d18n1~Z?06y=a%d6+O2$J!Z(=$J!l8T@4QO4o0C~%1C}#P@csOuP}r&uy;&^iKE3_Qe%&OZC@eJsUk6I zX^Mq46VnIVh5g2og`5kinkzf<_9L5y2NJX>{Qk%Ehx{Y(xZ#*ll4sIJ)F zPP+i?BWki6xw2l&VuQW)zHT-`h=#QdgwXG}>*m~$2r7<~A3a5Wb58Sg=ESl@)vY-* zFAB?xmfv326e}45T37=;J#Jc{RxAL;FArfO28iX;tHR~gycrKCDXSh(lD+5)T;gqF zzAI=HC5C|&V>Ff0g2i4A4KesDXUp)8G|f}2tJk%sx~$I?@vWtGu!$ignXRHn#-4tl zy@5R*JGE35r+WM9cLMYZi6n@dYAxeOTF2+LA9Pa%b|<9QBKaeutV6Sq8qQ<&!NyDP@MOho@U+V z$Rl}beZ30v8u-@(JjQpPNo?z{YEu)*;;fM=s>EL>5i@jpj&M!Zix&)yufH?U3}(!% zw@Jm=t-a09e)qQNBrAhSv^VP*d3L@-{j!b@iL!Y^a>E{`M-xz3t^h;%WrZ=5;#$`^ z#9_PPm3h0+T0e`9<1kWI0aiULkfQ@vsPq>`z}hP0h&@4!13>RzzWvl0DnsH2b9tr) zD**yA$@A}Yl|885&v!g#lNM)iwiQ!z6R~irc`^!Ee~d)37-aYIZ7co}``CSZY0j0Y8yZ{v(+ z@&z<#rY|sJL`o7QUe1L+vsml3F|{65q{uR8F*lubNosd}FI=fz(%W8wAAYXkt)iM2 z3x6EdCWR}%8%%Qa!nO40Q(mfGVKNDDv)yAP8~0@=j z;MceSuQ*4APRf!$mg+y=nt5#f&FrVM10_kq8t}$vDux`v#LKQqMGI9}mI|g$EvhB^ z@QKFIrsu@R5^QVxbjNxo3Hkc%`0&%VjBcN2;k8|@3Z?79U;Gl^+sW)cToiD%3DBVl zaVTTL5nb*3s`K`xoTDM(Za5s}9ERZvdQXfF@RCm_;IrT)f)*OMCzw6z^{d0Ufx%OM zEi`ERx4z?6PbLOs+rZUhLBYu0AnBQ?I4XZ*PCM4oV3d|*TAA5*XUp6N9Ia&Pa{b}nl33($z{X==fmkV~-VU^e#5I=cg?jyx4sHoN>R zs7BF+Yhzc?NtM>slGXM1Z8Lk>LRP;?o16bsO^j*Up81*^r5tq*Tg40W=9MRQ{t>q1 zVXkgjPZJJ!$$-fRRPt}9!6NoEE{uAoOffwZnMS8;`?I=S6mYh;tS6}XdePqGH;G&q znBH(lbK+sJ5c0ablX;H#MDN`PpHZU7Onu3%qfy4?8n==JdFlyEcCMekqK6!{p7idv zes^dwps31bsA)-XKu#Bhi%}d0HsJ!bEn#sAl4>qP+CMcCt|xDZXDInk27Ty_hyvDhG(+O1)SKY`I}(uK1xc<9g5hEW-y=^!KVF z&ms(}L)!_W(z>F3L+YB|;E->+ldQ(lBCD0^@K9`hJwKTml{Aj2VhOCwo&o!|9gMXxW1k%_Jc?ZDE-2&ft0x?M@J1d5?9%g% zaDLLQ8F2aa+Z9t#(_ILQtf!w|;e-Sh|5{jHy!RWw6yyI=H1*HX_n$L8ObjmZf7fcT z|4y|3f0bPSe>&3tV|@S5BmF;Gx&N_N`=`t5zk;#cg{f%p)} ztO~0D0sFnGbD{7>Qyj`8XvnySglP@t189HS@8NYrwp(vgpRXj1=1e1gXQYpGc0wd+ zPsoM?ly0(w#iSVr7Xtk zWRj=SbiS_QZJu`of(g+lDx4_pTHB;fLPFDAN4P{I4@MnbM2tj-N`ymnM&L+ysa}%! ziP`P;n#zvLZe+fl*-5AS@yE3UTLpSiY^eXf*kIU0U5<>4?t_BlQM0g45|w?S(f+Vx zvB8=)gw*gFB>HNHzedjN(r zzRmkC3d8d`kl7hvL&Xf8v*VT%kl!wU98Cu|K&QVMJYF--z@l^)(FV?T4uPtmhfeG zLZLlEG@!12`?zr;K(F{P*GEn%vBQgB*Zin zl+3s$Hc#!meK=Y8K4g9Ff?aJxY!WL_6j_t18UbTbyCGja_MZzFyJjEyZSLd7SrM6K zPe!W?dc7iqzHt8u^|%4_iSzGFh6zjubDGi4;Qy44gOBp*G+ocVvYszaAz^0ikmuYR zQMgA{$4>TH{E-?gz+00@_~Xrbk&v@(lO?^C+cyJ`0Ye8Z;C#;;jwF~I`sVjU5iuDP~U-0|dCxjj~3 z%jJi4-8fB{@}GOOR27)Z`n!NqL3iesA#iLN&?o2xW(05=yv3J)WLsA!3()hb4cVqe zMXs*KY-3~KbnvjX;9+`tNaeTf^tHAU>$b__CDjnKuL8K;R?i2(yuMXz)9xRq5oKr2{cyuAhT-loJ7CYacIv{j%=J0w{wg7F z0*5?8C5MyORS8AloO}!MeK+mya78Vp>Fa()MAjE5#C6zst@4j8e#)32lx6b-IW}P6 z4c>%{6@8;FWBL)vX5ueE%7i)9QS>r-YlaLn0blf~4_!CZv*!*UDs+cD-~+*1WvW&8#7TUE(<{t)&~`l#kQ1M^~F#b`#`LVCBvHBk&kS6 zv%b>Q(G?++iLeQA`4lRbRDBrKTz}-UHo(%FRq67h;dY{_)L5B&w8XB6mL`~xpqdIT zmO2!SRAn7u$?;2ap#qi=7ju;%mbX}$WLzxRtBW1ub4+^08qL~TFL%xP;yIrkpoAl{ zwBj5avkI>x#n=HZew(k94eA$ghT6R6(Cgz(Y%%K6dc!z{w&r|W-7V-teUf7HKkhfN z8IpIlamC>cG5RWYCl@XULTY-qJL26{|BIEx`_IP3GI+AL*) zd>-eY_S(GnC}=ap-5t`~g;|V+8beh0XK%Ki`e>EV!K3U@9;=9Mx<|ue?z2Pc9!&AwMX1#}`J(+8 z{iLs2zKulviZ68<9@Xn>NZX?4-j|9J^1=&OOGm9_g|jtZZL2p`>>9&>+*QMaU1k#n zYHFXVmnr1tKgxL&k>E`&-(-b`$uhX<#=ni}5o<)tu1Ma6zPkP!mfA1iALNRc4|>3u zd>O=~Vq7{@rPXy1wA?AY{t~D#_u=Z^(t5-mBt@#XG)ehh>_Vg|Z|EB>cYjbtkRNbO z(Fp!J;Pn_%ztMWZ-R_Pqb}5WxQIIz)P4U#H{IHxO+X4_8J^pnozO){{`-+yC1VY>j z2O4AE-4tcMEc1Be(nV@v$tu?F)ADGfI&Bv-&QkOBORlp&5vun|devbt%+Jz28uaHFNga}vXl^kDr#|Mj)*QF91e)k zZa{$_;H2$|4Wf%^QM{bFkLAU0td3UIE}SAW8yzKEEMq-2ha=av^lz#7J-J0%NVH&r z7zeg$;vv4Bw-g$-kvHkhmnFeYx5&$_k>|-B`yv#7O>=+bC`1RZ#%P77imBqo_qrw- zVnF-XjXB(HKBx%9QI3rm032_!+}@rBn@vZWuH^xmzgbWd}BDMN9 zvKWs*`?t~9dK>r#8y-g%p&&S6Lx-9xxWd!yU;$StRXz@C+K+C6hV*?CEFFYo?9lh} zmOLG)#wZ*z)>RR}CA*l))bPle-_euRoc29QSOtFXo$$UHtPoFnZ$U4;tR@_@>oW^}dA_r1t)QA|3GME25xLCWdt;o)H_tp-^aMqT9qtc#;6 zVnLtheN}=sAlso<2fA#wJQIb?X~YoN){mUn09Ag6C2w?WZ!#~pN{+PHP&zWTbF~K= zI2^U8vlW@Jjj+pw^VE=1#^oW1UT=B^A%+GX7a9bY(R^r-20PE=!Mt6oH7rg}NqA!~ z&t;S@w&)R7h_EME+zz;$8m>Ec+!xAZ)yFJ)^sxi3;2t!aCj+)!7=F(bUs#_>-?mL` ztY@hesIW)TGj){>%~JEL{5n5b8LjDs_6VYtX)!C9;(IhN zdn!U#t|l+5fF0MW-Mj@q_^|@5Hg{9qd2hxNQXMIH$~^?*=~+o3`&fS=p8oMEG-j18 zPlQ?9eK>cKN8D8jNp6dx+WWuGCzaifq95dlv9U4g&JW(y|CQ(q_K#Tc-zpG639gZiFn$;l zk8{%uMxzK!a?BjD#-vr!Qqsl9q!A25ThHL7>iAH^_YTfcT@xs>rl>2;{>X9W6`|EA zfk|+}ona3h1hIJ4B!_6i@Yg2Q30Qy-jnd#e0hv}An28*tP$*>FOo$o}xFhSi&CbY8 zj8SkYI3Vi?HDjHPdz+x|`QZJ<^3v>?2U8%GDO`G1G9I@PV^gZv?XOaI+c3&wjEuMh za9cLoO5cWIa z?-oUYtge^VAWHHYT~{EZo1(br|40tsf%wC1J3igw&})b?x{FZi1hOzB+%=|+9SHd5 zqo&%X+mNdif19=ibGfjwR1oyV%z3#`p!JCNWkl^&G}XtqoqtB9d9Grq5J-~C%f2a) zc(J^C5a8RB8GWs;aI7_zAMzN!@O$~KHoM~{HNENMrfn2jD1HYuirwy(?R?wH+37#h z!>u1iEWYmhi6pXb)OWA$Y;J9wIZ&yN~%U zymZ2lfx*X9wM$mWCzlmzG73xzU~I6C87*!UlN}rW7^;yJ)bF7QhHC24u9AElU(<(c zdAUhZ4S9A8(J|^5&F(g1lCAvIxJn86GmrZ2W@bd@lT9G=wz2G|a3f*U-)Tdi*|~Ua zo}bm#!YEyb*(#g4$4_A4e_dl^;4*abc0tvf9;)PA(q1D9Bn`np=j;$HeS;r9P1dJs&^G(yaP|-XBMQcj$atXx0BFoYa}G zLQB114((#-K_mj6;@PCK|H0se7_R}noH^WB4-^uy%|wVHS69=e;wj}+E{D}#WS;y8 zenS}llRi1^==RTZ-#>DbbTV&J4oh*1^XTXrCqW4&ir7H^yoeqhYAjAqi>-%x?0lnJ z-q@aq=lc>+r;We}0GA;&w|VrUW}0SZ!#QE(;(-@CGsASw`K@cau&GSrZJeDE9v1em>(gxG(>&&0VOP%)&%l3@JA&uFo^Tc5) z&mqN7>aapIm_Wlme6IxYIQa?VG}feWtS@`-3+#S*JnskHYa8%sG@&d&5zm^ypf=+A z6P5<0F?RT2PxA+gv7$GUM|g?-ex?|6x~}}Q6-L<4%szfT(2O1bznFW=s5Tou>lY1{ zgy5Fa;2t0Zmj-tTTHM{e)X`wUy@eKcw*sZOyOjc^6nB>@ZC~zto_WtRbDmi|e7^9gZgtGt-(c(9~ zLM`6QI#xhbip8u2eJmkVCp=`x_4_kwUHuM2Z9iR8ylI8?2(_b3T1qdu4kDy~w z=J)Ce$YgA4$gf6-igfrh7ki_2MW03%kfhJ3 zto9WuJlvov=Pp?TZpc3GG*1k4?A^vyj)f-aRN zRv~EmdcuZ5?Qtfn@^LT%v13U`JCquist)(WA;2wT{sfx|gf}l@zk2kw3}?qthOQ=P zbV>tq!b~n0R)^H*c`)d`mzoZy#uI*W1=qPTu4D7V*C=X>z&$8_#jk4H4q;3kiqa_g zxM%M(ahbaCV^XCo<@Gd)C<9AW_#<}2!uV(Vr6;BvqwiX;^Te#*{>13IQkGA3tXVNU ze+{;B0_L@DcOOG$DQ)p44eJ`-O|WMKpb(}5T(ky!mIgtRrILYfouKc$t;t;z-p4Yt zwT9>sO&0;1`7HLe#l2&pHGD&p+iOI_`ie7JSovlZ`^1A z#o0`o**-x<<%RCtUjw<*7)T0I!ZnfERnfVkCiOX}{n%pdhMz6hVbpIR;PmCYg+ zEiem7nBVuXkjmS~Ee-#kD|?4kBu4D=9{gh%b)LY&&I50{Kv%^_^@I;PK0lY0g6wp$ zDek}643c5J85qapOlSpet?1;-FBf_}ctj;67T5rxF95%}Q=J0fVhb0V;Uvbbe>AZqv^zfv55xwn^EwYwUNQg=T8-*TmJ}TdUs*r*{RD7fBk^{6vgPh-n|vX4~!^ zo4*oFaen!LN)ql0yMMb?3@v=FO%jxC`O{DPskF#`ucJu051QSzMeR$%-i~5KKCn_E z>0UyenM8P@s&%B*Ha}6QnQ#yg?YaKJXVNXpxGd(0imz8nXkQG`SHrJ}QESa3tL-22 z@mjUIHZt8VD zQ{~GeHI-#=59QktLm#O}(L#JNk#KaAYU@U?LwB3RWQ?=%oPDv68u5#N&IqBJzB@@#_M ze`8_p)ZswMssMf^I(87OLZEiKVAXvF^wg+XI|AmJp$=dC>E7zx{!yv>?JcD(r^=VF zIM_M936jIkHTV9YNM0ggUlz}Y1d~ugirbRma^+OZz~#R3cZt&DR)Gyr`2qwJBuHJ! zz!R(&?LH&p&1y$IA&r6;nsvKbvq(4SOr^sJug9s?fc%oB>$(5-wZV{2?o@3upcn@*@a##;c zWuK2cYY-m%UCJ>$G;ZO6M<`p;UpzedNO2!8HDyK1%vHd6(#b&4lUg7O+KWUvB6+mfk|+K!>_LIOveGBfZhuhpQK-%ru=}^CgeRxGCt?D+ z{9`f#?8{GUgzB_nOCxT-Ep?M7q+aDqLq#du%+62V)`HQpZsil;=})dGTJ4cnb>L7% zVX%-PbB=2+jf)SP7l(?%oMu6r=A}ch<1(0HwmW1?w1l8)lodFwNpQ~nIiOiz*+#8? z_|?p}N;X%v?L)S)*n*i$ffQ}6(US~a4h2HY+o>*jKY)-%!oWt$1n)19%7(Va&R6aX z*1?S9BTnZ&UAFFCphFB#p;dm`412}FsS^QcX8AW?!V4D~0UFBowLMVYYH&J1t!CmK z*eH0!4%}>IhZD=MfcGy;aeu3}e^aAKG_}BJCT1G$P@V= z2lD>!ax?*8w;nQ$LO{W=zecEC8KKI95SAvBEk_7LXd$so%N)UN@0*GViaY-D$kp|1A9v30*m~!JbtiI{H05|%dw0T_Vk*qA?AgQSO*EXSR#jb@A^O( z9)rPCEG@Rik9k5@cwmxP`l3cwH@|$teejNtr~AA92~yeM4wn^A$Alm^)2Ax#y;DfM zLY!ED?q=3S16ru;Lv(L&5d_47^C%-WEEqLPBxq+c#H-u*BL_gMI;=7&Ry>9(&Fjwyc~Tp&5E%c^ zN9NoUH>BdTVbLZ{jS^E)t4ufU0UHKt^?Fq<@y&aQGz;{dk`2jW$S!9%L^ll<8Q|*g zU8qgxZ%b+tbMNA0;Xc4VhA6VlteLj^)UwG{|3d2dT5 z0Y48VnGjCAhiG?|*pZ5l&s&LF?ZL_Cos^IEW9(R<`b@t#w>=`hgq5w76kdGACrvol z_s4503FR_ul&}2chwN~(%Py+9Pld^;CR$Hv{ra0%XvxKbwxG#(L%jDI#(Bo{OZ!!_ z*+W!M%dKZM)AK#HT0TmrA(7SYTF$nFV&9agZ@{63Mx4EJeLA8XbW;$N6BFip6G_g> zy3)hDYV<*{LBI=8RDNxSoVf93dro!tqDCe$MAs9jk-T>#6XU#lwPjC0gqv~bdvf#p zQt9Ga;j`#R+t(~LC}WgA%BU}OX+nl}^Olr>+W=}Thzp#cjt>Xp*2|^p)S3yZcd;!T z)9<8+%VrgXZv`z}Dr;V@s6Ia0mB;B{O0dOQ74e?TLfy(yee@T=?cd{uhqBh*H5+g4 zzTPXbj;dTiB^mLX$MC5W6;ng+h_M3`Ufg5d&Vu7bUO@4=y?}9xQJCu!#y;+c);nv6 z$Zq}j#C+dfv|R;nm)N!~)LdO%>R)$WyF4^tTGsR|C$2nmoBH&Y-SN5ch4q*{M3Q~XMM^X&(A?-mBh zy^OtH4_X^%v``dmk!h^XG1#UFLV(6VLUEL=HP4pi9iM?MMpyutx|{-JyEVIp9iUbU z_U4QcXj1sb4P-ejh9i%!z~~~kQ{NyKSr1_vZviN4Sn@Wi?B-I6JA-D5dUhu}dT;`s za$K#yJKOta4PAO^n}DM9S?Nls>T;aprq5)ZAp5Au7fIatP#djJ7LRfP2}VdW*&Jx# zXSs;=H2BKXb-bV`KYc|of{;iWt?kJkad39S89;oSnvx80tdQt$Bw2pOdSrcnC##KL z$&!DaJ;qTzi5h){O<`gef+Y>NHYJ_W_t^x3ZHuGWs9(JDp^d)2_#oy7AH8{#2Z$bMH8jHcqcaBOgMor?0M#Q@u{x zfy-fHJ6#90__O1IfjIqKv@3l0hhEe*KlkV`0NfiGZsX2EV}Onw(nxNb6&on4Y%bWg zqN0)Z8M8I&m7tAZzRNV{aa?8j?yKlmsn`>DzWO~vl3YUza}TW9l@+2XFi9MN)G3$T zP5;Vzk!)7}EQKTA2n_lqRc<%tW#`v6rN1X!`Zy3=-TxNU+htjYCZn*YiSC}Fl`TjC zK%;Ll}2kc9nJ`Y~_cC;8g3 zwrA%~OvReu8cH2QRZ7beNj@{}YQlNe(?+q>g86U>zNnzHwYRwsy$9yIUV#5-nTdx? z*+{@l7smHr&ai;r4|X#?fvzdu;wED7=9k#CvwA;TUwu(4QfD$jzjJ=pT<)P|ax`Ic z=Rv4fy<<(JMw%0;q1%#Y8nS^hWp(~Cclm_AHuIz07&JZ)uS8?CO~hTxshFrK9LB?+ z&Of7sUtG&pEz^F}^ZA`#4Kk=*Zvy?5O*vwK7CbpzhnumWGNjOxzP_4IgifD$8uU@| z)LDKq7ZZ3w?{;iWK=majC1jtI{t?7#y*o9Egtt3fi?({64qJ8grc*#*PWaSqnS$4& zD?B*R#&#H@?z0Nz>U%cNMZ&(6%KRs$8$ra)Lp{w1_!^_wyU`qs&;v9Ui$8kU5&To& zO;&@wMnc2VV?I{fEzX8JApNo8;vyaFu2Jo-gc^JaxYq@l6O}2uHasw>heo z^XNC>9gH}HDw2;6P>%(TmD=ldX-o`hN9_rC*8Ln7=YMZF^_9I8dw4IF4Ln{>adIh0 zYvI3-Vg9UBHF{-wqr4-_R{!wmbKZl_3W-|L<419_@yu)#(mGuhZ*pgYNarO!y=|a$ zebSsF_500N)uGy*`FgrXH<3-zL%0mq{`Ek)A!&eRtUi`%$-0E|+jb+3X-dUxQuN0WJ2WP6XXtXP^D=8O1KHIdlsyMQ)DOiJ)!P<^+uuA#f`uh zC-BX4j*`R822PH!n-hZPaW3DYP{L?=Nz!tQb5#YLASj1_2*_$1d$IjdBq zmdmB_s94_ub;=@yBgELqF}}yII47x%Cg~d{p^d`e{GudJ)n1#mWz!w*$T6>pQX5ag zUJsn*lrjl5PR7Kt-$`sGl`*V28)#xz-jsbru#aJ7j7%Dd643E0^&pOo22LLOF2OL& z((xnSP(%UVR#rH4xdyxA<3&igguAv1UfW5s->0!dW?^ykcg%Qoz)g8}S%+5{gU_xe zo(z)1_BoB~3$0!{fq|%HF|Q!&^WnV6BQbk7v4iDuo8B-K3V2IABD#I;0CK{cEHdIk zaO{M-9vw+W)PBl~ksn}1Hy~;;RVR!zrX^Pxm)%7GlHl_szTW{N7MHwgx0Qj``Eo6| zdfx`!fM4r^|{y$nIlVjNpe=8NO7g3 zBvw<*-86%7h4udOc9_r|PSmV&<@}<$6;_!@5XNzH5`)}!YXdh7k&d>5^FHEG0da`ow>2p~Z5p^SwEV$GY?=(45gFj71_ zf&fuG>?T16@|S)D>9#fOQs7@WccQm&qX+y(O-bqiwot$AVj_Yvf%V_6d7l(2&3@4=xhfao;{mE~<2K zpzm@;p+({H(e~u*T64aH{qaXSm-)jHmJBU|m8VPtAS~pDBl(~p`<5L7ui&(eE0`)h z+fbM)s;N*q!U&nIGDnazWnGG~7w)F!rJY$U(I z$Cmmf!)L8}h%_TGwJ1av_-b;^9{E0g;%4BDyq-kO{|%E=s5SFP<$V376D`{B%Q}@25%wj z?A?Ll7Wp{C2<%^Wp0It^eh{{1Z`(Pc&}Of%&_jlegGlHd9Z0>|h&e_Hna*P+a6xHD zi-~E7&Qms0c+aKb%E7t}SkHZ9#ezF&@g@P^rnm1?Umq>EWc{V2IOnO`XB;s~MkhKu zq@jpmU)^uv^g#;#aN-$Am0-$5o2*gVrcjLmm2q>^TeKjrimFB|y^Q`(voWK(a23Un zzGhWk8V1|i)5^u8#*r~K5i5CosCWV{&OA*KKI8%d6bqRZiC?tOd^PM^u=mk(vdo>v zWc`hJX60>_>yZWa&bU;9iNwl4YoUDtM3M#YkQx(LBmgrf)egEv%+9Ty%8(Z@*~*&z zcq_7gG?)q0d$I76+YL9ZTI1|umzS|eX3SOnzzAZN>wGQO2s(TgUh!#AfBxDWQ(Y?D z@a|DMhX_aN_6_n&le98BxyB~k(q$wvlE^O}^6eU8)i}#toF>0;703xlY|a~p zselcGS?@WcuJlpCoYIdOqO{V@fOH#ls4ImIMwS_9oRle+W=@*d~bFpn^-06ljiSr#FhvBUCd`$AQ%r6qJjlzLu4toV_DS!sT&RoG?P*g5ZmoCCff~=omztEkhu=gAO}i=DUcr-!e}!j36=9)R zU|I2(QIec7&|EIy3V;(vIC-16B(X{UKEQ}RqyOaN4`NwFgiXJq&PgrFo6LVt-`2aA z%lbVZUW90G{XK&xgo?0D~0rw!e@ph4WA&ZsY&hW^8BSsz%?%nbb4s9tup=? zUM@UvoN>E8=34t>H`QASTY3<7fFn=FAnXp171-Og}8sZ<%b>+InJ>wrYln1ev7I2C!lIM$sx<)eK=V)nG zOKH@QyOP;nm@xVRo%>_&Q*A_GbcHrsb6Q)e?MXw?^*L&TO@sSo{p>&8Drr*1VzO2t z*gBd8DYx$BoELP(>12;XE!HQT+u4Xax!;>qqQYv3#9g#2H-jD1ja_sdgZ3OvNqxAr zDgeB_4@}o!xpTcw(K}o1iu})nPDoQQ{s6aqeGF$}vs9{-C($inw$D`UN4aQ%X;Txf ztK=m0uFYPPE>pa3Xs>mv@=gyd$qtzR;u&|&eAp~v=#kkVPAwamO381B%m9V}=cNRu z0N@IUCd1A72Zyl9GbUC>iJ$L^DkFE@=6b$Y$n!sNGv5vN5LGMMlTmE~f*1{5g@}wK zx(Dg|p2~vK1A5UzbnWP5t1u zY(;!NPwgQ0GeGG*wUi+z5A{NM-LDeU-K13+J_MS{rfT#W&1vJb+G^;4aK)L5uF{OS z`a;8mgrVQ^1M_W85ldx_kbwlS{E%Fa1|<1Nv`_#GfBaE1{Rx2Gpf9eLeUw`aXYLC& zS+iu!?za2eQ1U!pxL#OsJP}sl74lS^h|%C7IVQcz?^`v2hwGtz`CMU+_i=l*9;0=> zk=tD*mt2~HA4C~a2G$ci0?Z%$Hod6c8h-iqszK*TPVM3MQ~}XxQzEC^J3;`F{)b7s zwO5W&;b9(XE%r>g9Gpz+2@DT7#1moNTkCfR7eT-Biza1A>;1@F2O0Q(=gMR-wT!0x zdNT3wcwzPOM*q%;|MTIHXmE=#wSM661NLUjbqimmHCX*=!`FQv(_PPw@9+-KjW;`= z$5+yyJ~}@f?J(h$+%7@a@tt+8HTY(G+w~HMMSEm5@Wu{RBE@tX)F8mv82z8@UVVI5 zEVax7rR_sQXHTnCq_7(O{XleohZL~jgsdaJTq`d+DO2SGZr{8Fgp`c;LfON?NN~2Z z-{GxSe=FIyx2H}jD#16kC(F*U9fIF9Yvykq0WQTyu{a)IN)>*%FT?x6awA9WdGP?R zj$b|=xRqaeHGepc^FL5G?qS6q`v9u}ijA){efatu-6sJwow70IcA;@i4x9 z$m8uM#Y6h!n)VdpCjB~oUe)CZA>-(%YNvwa=&VTYOWoYo%KGGcUm0&+;lB1+#Y?ril9kR_wCiI38 z9Y{7E+%41_4kYdv2kVywD8M=YoGbL|sW|#3QV*2U&V8vzsG#Sfr*^jdBK zsb^ork64vP)M>`bCiE&^kQY=OuxH@(X6Op-gCKsckJk3XvRq@YJbhk-(}MPEUh)xt ztX)Zprq#lT@vW`;V4@`>OFXef%6`P7gAPA8*7g+*S4x>!U7dijb_c>6zs`3$H&y{a z#+>@R6JgrUS%}dZn%^e|wn0V(g6sQM@NHVNfgR2cB+fZw`3v1#oxf5#qkf0C^YnGg zpwOD`SNduUoSQ$4HSx4LylM|H&&%XC$M8vpf!)f|_@pLJhoLLPuok%2Q+J&a@~qUv z9e@4V5Vha6Fc(=0_Fpb$?=Z}-hPAoN79O6?>o=rnHe9J(YTTrf;2P+M6ISBtEH*R> zsa)DMI&cq<-6QbJ>zaYSJD&l1Ula6e->Ij3zhjAD=PmL14F{u0x>qgxEG%o`9QIjL z+KpU=q}Dc{Bu|Ow^&M2%`BSQ`9+SHvdBau+J4LHU*S(3ewlDq?_`25o$+IpbN(Zsk zya_dZ&Oeb5LZt6Cz3YgKvbbo0!*%#Gt~zBRe(qME5{*P(E|o1adf^yz-Yt#p^6m^yBF-W<=xXydn98SEbdUnf?m1pEnS%lg*o4%riCqmvySuI6}U zBT|z$5?i2y7bF5_9dBK8wv(}$eOGibg;OpOf%&gF6n{&cf75OVk$(zdiv0H>%>RLQ z`)8}`|IFU{7iml6zhpil|HsV7|I*$<(#J>kxztU&NYH@^@L5{>EfAP&C4h}fFS%fp z604rtk&_~8sOpw|FlyO=FS>uD0Jm<<3(hcAIE!2L!=F`Bqc~hIC(E82s}e;O8gQU4 z`+AHsKx%wd@GhN!&GmAm8lwU)zKT7G&x)%PgoZd|<{`ZutTI{AtSxYXFW%~IDmBB7m_)rzNQ&`68fgwRy2;V$l&nzZ$@Pzz$_)QA z2@iP#$An>vnje3>0`$(-9ioI-Itn{dc?8+yAV`)z6<(p}JV%^&3BfioBHsSAY$O{= zC}afgffX;wI*t=G3cksK)8H!PP25<;X9AI*j&tZyLIaJc3zDUj0eSMVsZ71{iUhKQ zJXacYN~i459aZ8yyKrHClN1pGyfrj3Du2%gF1$fsO#!I+iJerA_pxDUYXnk{xBFfp z5BqgV-_S~*LVIv~1-1OrWRnd(i{+Iu-AoUV^Py&BLHuqEx)kPGl`{fKMYrN8cnhI$ zQu$;}4i0k^tThm_p>NmM;A2;hIty;qe$f2)CQLN+SMwAN^tZI?=?DL;) zV$Cl(l$hj$*+tDeh0Nw$WHR5$KDEv|c!N)2d^x!koi4h>2Fzh&bo1LnNbg*#Ck+a+Zt5A>N3@wk zU);heZtXXHMHkcx_A1o_>G`+)_V27-2-rUF7MEL7Q6QO6XzwM?^0N-b^41%h5ifte zvaR!BsWZ7jTPpQpWckgVy7-S~*KZY#K1_~q1e!~vuvtpV#)(`VK!CRH~Qn&13J?Sr-dAM>&8T>il)=OiK`2Ib6z z(hq*&qvy#V#lgnWkn)X zVp|LP90KXgCBw*T_h|){qVufWr($b)n7OxMMQKG+_XK6eWP`b93M}YV>yaa>$~Di| zrL&ys%D-i*w%X0Nmx*X{5aEZZ9W2}=V!7Rv`t3MvjN^DB;kg+#v}vRaG3Rj_q}nZb z+y>SK-?V(1=`h{BYoH|FkBb5k#Yt!k>y=mJ1DAi2sBJ) z6Hr$}0MKiziflnF>+jxT>PDF@aNh#UZN1UQ9`bB!Ar7A)_Qt!oDEn<|@M{%?US>-dNh;7uw*b zW{Ibn!4g4^ckT_-KbJ7Ir*@92qgJ?N)s8bHX03a#hbr^cqUl*HX&^Zob$!FNkOdM& zelLSxukH4{lU0iMtI@bGO2^}2UC4JLJj!_=25|`E7!#1bL!xi?9{);Ao*s$uIWUyR z5hYTKW~3>vv7y#}3J+Ofn(oc!Dquf@>sk2SRrf-QM( ziGW&3jmMCghvq5tozoN|M`5rm?UydqC}VKq${rzZli1P$K`}HiqHY1kn2X*=$`if- zE%>l39m=~DhkJlgVLwyyqFj%)D_bXVdrZ4`7(v4x1h~=Zxn#6%yC+- zUyLF$(E}~rOD_1W{`JlSzsehu3hY*1Js>Gc)oa-1o*7HebQ;YHnN3hF%eO4$U_pM4 zg3yP%w)kX`6RlIjJ+<4~OvZNUwy2rsj@J+mbrnKwG|!4BD}%%a*FF)I61l%@4bsP* z4K8M@$zTfh(hu#uFYZjt%=ANF+O%8RYOR+(+_8{wp5~59@L2TS{dg0@L*~t&jlf}u z2piB;nKICz7?l1^+H^qU&I8;CVF{Q%ORMBILLPVDv^4Le+VG%dlF>0@yn!Irfk-`# zL6O)VL?wd+?{^U}5)N8Fy_Z^780_U)X*xNFCPQ-GaW`bJLeTOE3v65&?Uw|< zNO@YVm<6Bq_?1tIzn3MP+YviBd^!+*fo)bdf3wq+x*ae}gAfWFVc>Ie_@o$FN9EOB zR3*OQvwCOu13|ZoEr{~)1bXXJ0oU`%S%JpStXJpzIo~pHCiS&`eI{Yy2VGhmQpUq= zekin-C&EUV%spjf@IDG|Oy2}gPl+|qp!;mX@-V%-PskOl-~ACYYt;8Gk!oz^%QWC@ zEdyNU53K$ZdYIRjm16^&%CD1Jb1r?mC(~7-xzknpV5bM4+ZSB2iwF4Xv`-G2i=?5* zu+s>7pc8|qy-&_>{4vk3KA9R8QyQB4On#M;jxnC8SeY|vVEw$)m`8fDoBHE(rnK19 zMaI~^bf&Kh@l%%BW@Dk}(9F8N=Q;$qtx}j3p5FQTE+c{|m~;!z!_O(MhM%4cf8x|N ztjTPxe^aT0Qru9Hrd@a&Q#y?I(az>^EKyr`c)PqOYlXvwK}e(Nr_M)x7o6X>PWG_b z_3-al4zA}?cO8VkgVuvGhs7?Ux1i5?wU%4SU-mB+Myzp6Tk1eTVAzHZchw}kO&h#i z*;IH7Llj)uA@Dn`F(&mYG3hBoCnl zS04egxM8=QXAeiJZuYp_Nd~nKvT?gd38#BA(8Dq8`dTGrp+!na9--xd&dBmsF|8G1 zwbC_uH}l-wh>kDRJBPb$xXfZ{$R$s*Ui7PQ03S}sdf&92SA zrl@sAnhck)JGocxrj_vfWJKW}d@qOW)fkt)!6u0i09#EASR#BD0s3P19zJOv7+(C{gbkes-^7(WZl(e2L z6I_=m4t7$J4ds7IK#|N||BF&Mi*#0DOL*ZE{s0L_mL~ZN09NY0*H(4ibc0I&PwsC3 zOgQWIhEhirpSNa7 z)ZOcb0}NSRhli}ye)CNN{{I>B`&;q+r;s1=KbmU) z=$s+{;b{r}52<@Lu-m*{Uubs-%8(V`=3Myi^4VX(JDh$;FfT)aK0bXIIr(3OFpB6B zW;Z~b{j_i0xHB1}8gYuP&$y#x)QB?PlCQok>1*{;1>C=Y_pe6?@OgumLk!bm2?!YZ zyY0o96dle<9VP6LjPVDG6h1pMZfP0`&LZkLD=?Py%DkB>ZtuJGllx8QWsCmqk?THR z8D~~z1CYcBfF3UPz)zAvdq^I4vDZUt8?@uzqyI&iajy2N>=|h;fKky!c+sTK9#$1c z07&*tvuuZx3L=(*kse}no@XM%LQ@cN=n5ZY_4_Ty$BgbrhHsJ2ojvMKq{46?q>emh z@MC!~#*yg%m=+r);@i5MZCI(lsn^r`wj-%TAlQLkOran`l+cS63uwmeOZg%?8tg;g zIgy1H6|}8_9yeF=zQ*mYlc7A4Mu!;@$g78#z2+Gib!Y+9{s{V2So=e%rvg$?v`#vF z=5xfNHqp-r$zNpjV0`l2 zO8;R|_nty?0gg7Uqy* zMI{k~*;MmgD*!w^XApsH6q*phUZQ4@abr64_o|yF$cGH{Uq9MlQ4D ziivKo=v{me!5LEeKdWExro3&l>bej;?U1>KIa-vGzXMhd20GGYs@g^%x(t#I?!REo zO)KrXw0uMR$G3b@?}J4774!DjQw*#Wovq~nQOS0@dw=r$<8$4kr-@JofOun<6^5}Y ztwXi(WnJBax-WAk)v>=D@8$PC=9Cof%Nh%@(X5jXYr4$+_|ol2CG6c|b|Qk0hC2*r zyt&V94H0L8h_abw>Z|x{<_?<+_y195&bRERenm~hg#}X23E0E)cceem_W@?06t11T-O)T> zkeC>PNOptVD5yvjj5F-p>jV!13LFk6HMi4YOG$0)f*|uy@o=(^SMMU>W$SjBCncQ< zY;8VTr1fOav7tGdLA^!ADR}8FukLp+2vC+3zA?~01{a1nrBFX=ly|9aRxt?}&EMqL zbIk71bohOqCQ@RrQ}kOQ0LNsM(txm}#{YJTKx(u?8W@YaR3XJ@l6lNs?#Y*~I|gi4x9y zo3LNH^1n*-1hOzYLA`|>a4B^^?{H_{{%~TLDM4{DBNaPS56)lKn>`*eJrtkV56Ci0 zl<6~}WMiZO%wL<7$JuKzHk$wwrA5^+_G`GMA_W@-kUh;Ov{phAVMjKNUG3nnoG$(# z+=#iHuv7*zr7lot!|S;>;|lhEm<9;0OSXZWW4NQac^pb6jC6|Gp#<=~>TM*-=9VlhdXmjfouV^mg3OO3t;ax? zp{zWM0`ck%=}tc8aKk-5&SN{{1AD}{zz43<_r000S>_jxH5H-7-i6zF_I=sy2)c$T zBFLdr#JB#FIb$N~7e3+B%PiQn!5~qNL#%e*E3= zBZ+uSDSte4?@8s}2)312;Qf|{$ym;liPYUFDEaMCnd^104S9I|qkD zgKetMj@=^yCLVSEax}Y(gny|p$*OTP^UL=KgAau&XrQ^trB)7awoj3ED+x+D58o)v zK9kFP8*a4T3Vj|}| z+9AagnU~Z*x2P)x1o&>-06hpjg++TU7kC2R;e^br7I&z+T+#4mFk9JU{hq%RTQ}8@ z{t4h)%aJDx6Iri!VbB;d#`ke(bk}yw&YSY^o(;7U;obPK`7tlX;7x2XCZf1^GUCHK z<|?L(uTjdKJ|@I4AWM%s|JoL#$6S;dOV(TqPeDXzWwK^8c~0#kR!3R^%}*b(ZTx8+HswGNnG(Ki5e^@B-Mho_`Qidk2$?QxVyUA7pjgY8Gz$BWW*B`kK}B&xt* zSJB6+SjTiAOG328+0tV=(oaC+plHDHkm+rIw3#O2W`XR}Sf7LoIJ8N;#!KVPSGR%C zBq`#+UFD=#+JpXnaq6{?c*s}+-_~BghuaTP**czp=Y@R3VQ=d8-G~ukqvy!SBJ}Hv zMflYp-ahy9TzX)}li7^%!z(5?(_-!+^-6A3t=phf2&m)Pe=6!dKgZMkRx)+3cB_J2 z;P7_*Tq$@igF?enTDC!fc0v2=79%FOH1H-LP}fc&Q#F@AGql!*J!Lr_>1^PtvnoCz zCqu#GRGKQF=Cyt;sDtO6ULB-5E`%HTanHVau5_sZ3%DuwV52ppB}DErw*)(xyxDJH zypF@!u4242tqLP@QW!p)%|_qB4v zecVCNO($|cqi3%_YMipdgH{FJ?S*ohMEf0qcs;Ra?o|#koUg9o|sFjJF31 zXw{GR{vn=J^%$3!0gsH#+mGnm5j-Hz^Kgm_1Xc(s%n)Dq((W7_ymh)j?hb1WoIG-+ zfe0KVk5Y@0YjqV=L&$%E^-SLHNzw_B(RhNh60bP48K|r8GEUn(E(!4yDj^fPQ6pi1 zQcP|VOM|zx$+^*4*kuh@zB|Kqv&kEY!fo`9E*djGh^Ke&o?k;T(saqaqrzbmBh|3D zBy4>$*?Eex3QUD8`eugm7a_e+wILyeTuNBd!i+byKbVdTh?Q1Dg_A+d=RE+iK_TTaK)sl@^rNw)V04K<(h_#QR+~bot(rwnj{8l ztsb#?947V$=v2-5slyRk?|0+GOOp)M?z5AO8VVZ;QF!>rJhKs@HN_cLN_r~1)tUle zcS;txv$fM^7px6o6^@J(nPROTb80RsaJPTtUX-U=s7q3-RN~j**6k+6ec`to#v8tH zODR5{+Q}$dNmQ(OBCNqL0-loIu#GwPn4h77*Ob-6p@zlnY|h>(tt_6 zSX!D5D?il{WaxOOvg|kLg+o31A);zI`HACE6Sq=9j}uHm^;^$QlPpC>Y)QiuMP8O# z1ur;YGD?-vVPne9#sj?xD-9L}gaGDy6h{{&U^$?JNej}JDtLsTNbH&y=`r3rf%$d? z{>3t9P93)dLNGOGe!9`iKpdOR5*ub!vl2UpT&o@ogNOWx!qyfp%%z#C3HgGH(s}u_ z;gQM))?*vW@`uM zyuD#=GvWf{A}ACH^@yiGD|qxf;epc-$0>n(m;9i;unNElBz?`oi?>iGm8#hi%ux19}-l;YsWv`FEoLz&n`kYZeAQIMa$c!TM(+IJFlIaVW37LnG0aG*o0lz4y6VRhzX$BhuI`Mxi)A5O za)d@Ux?T2}#o4sN?r6>b(N>hi4>Pb7!_`6l)ZK317CkA9x|X88ZyU&c6|Y1{{((Lv zQ&m5BBtw@`-(LG$`H2Iu-N1L7li`{GoT9fAVOWaP|tbGf^6Stpv#!b-q>;Y z{JmEfZ05dEuu1b%ankoDtfwaFSVGYxxi6y+ovf_HN`ymlNY=`T^8!jluenF5ujaRK z>&JA4o!q8x(anbY;mTs&>tY{Xb-G`eD@yv;{D3DyKNU8>cDKGxEK9&<$6`ywQ7NQ@ zUvvcE#Nr5N)o{oH$sKMj+A)mJq0X`7%wHC*oBSZ7Ko!T&Q%p?Pz|ii#R6`-6fRugR zbGmww_Z2``N~}@J_u5c#%Rr_0!T9UD+m8}bwKz~~=Y`CbjpN3nzZDWz07(rYq+J@q zVwn-wOayJj6t^qSeW4{C&x{z?y3g9i@+?qu&IGSwLY#IAyPp&wxr8tEdmDf@{Xm;e zU|uIE&jK7fJRPgY(lQrJ^Glb&OwsTQS#%a4YLU3OMa0Xd-sYlH-_!vzvKh` zKewj;44S5XZ|!b13R%^;-zPoZy^`nU7VM!;EqmFmkvx z-k~$7OmT-GBMbr9LCT)iSq<3#_Nl9^NK?ukw}u4%@~LCHOD=A&K`P=V(;;q>MPSx{ z_|#KA`uQHjHew8FLUZwQrG&B6l-h%-`9-}R$XCU9c&5~i3A_$~X_k)9WRD=OcH#7^ zwc6t!Hg0Q}>gJ(IBXO9k8`=kHLQwF-VlBCseVdB`!;U(gN{)DSWDdE&okzbij)Tv# z1O=7Q^s+T$E&Y<@H+a)!(`?fC!bj15FPf)P2%w@migFNn5EJVzX1(&;0>bB#a^OFf zG#R2;#+EY>8g*_jJ8OOf>~f+jZ92%kUCfFlS+Jf^NwD-!ib!1i<&7R4O)Un**-a_$ zNSN91fzGUrjS7eo|>kvWpxfF1ab~H^p-xap|2aSkY%JcBKNF#SM z^#Z`RL+*3|p*RcCs&#Rw6cT;hc{w^i*Z)UW*Madndz|6b4~40Y-@gptHg*i7Q)hGd zrR9Xy9Kr$i^#tZR$8TBWPsdW#rxF`cGX_)Ct ziqc*Z=Qp{4;q*)G2XkfB@|+QrU`YHLO`2b*5E9zJf)dIpIK`9=gwZ?jFP7gO@V1Dk zbTGD@yJzviONhxVs47eJzFH2^{YZv^o0vLeN@`~3)mtL1rgMx6ldHbXUtA(ljax2J z>y&;=xJubyT%r-Z1jXSsDFXbgJ)wkfzLL}g`?AI5_~B=*5Rz|OOcDhT-FFKFzdS*1 zn;Dmgrq(~aX6oQV#?Scbe{f3Jmi=Gsy?G#%UHdqG-!qJDMiSX;>^n1Kj3vpwlO$1E z27_VDOk+r;vW4s+Em~v?l|-p0Dj`X-wrQ0RrK0U=_dEBX^?9G?ec$ir_xpYS_zc%M z=f2K$&biKYuCv|e+~>UW7nKm6OMY?GL;918wD-D!Ct!CJWBJ)z&Zm;XhVP5cT2Q=m zy|nU*y(CWw(Z$R!%O`5%UFCYSvo#;MMO^z_=d<$Rn)AbETY~nEhb3WKRa`1JJc+G7 zJV)b6_1xfNBc3Js5r3}w(Od0+9JBGfTRqPC}Ru!1b+ zFWGDB@UlD&t^UzX_~MACR=P(;luf)Pa>~wwIg8e370mNA*p?xwXq%lQCE2%pt#idZ zqt`AY@_Q?m+bXVZZVXtlZ=9SdS}u86O>Fu7@INC7HalC4f}ig)I1^kwTQd*swSFL6 z&Hhmpp*F}XQgA}aN%c*Bou=?>7jNdmk~`Ap-rp7W?I&-aIKNDt&>V)|jmM3Kwe2Uo zkd=+qSXj`9Z7pA*tU@kK<=f)gda9rmt|wCqZU!9e-{=Kj>~+Jpj#hYBt;l}1MikC9 z!q}a$ZrZd8N6j^>UCNPJDyJRG;Qx5|jN8{0mhC%3S4a`!vRZe0`q^jjhdPEUEzP-_ zn%c9!sP1%2y|iX(^yRg3c2VR{2N{wy;YaTeCulD4^4q+1cC4lQHo?lQ_}gnz-`bVG z+Js*HRyKO}S)q%|)%ow$7v~<{Xmqhn%ohLpCEx5-c1_8gFC}D+f@&GoLLXEtU0yjg zS9q!8Aor#B%31oe6){(vY@$<6X__~mNNW*W+e<$~bQVpR`id2z2zX>9_8N@2J{=Rs zK+UpJAO7UmuBi~J*>>_sOrw1KT9&?Io-^tOTP#i*FPI*CLe8hL?P-k?#y+h5!p1Y% zSVakpu)^BnwM<;+M5NM1(Pr->(zh={uB8}DS=;JRe)^J_8sR{P*0ph)9NyZOCJepQ z>^UM4YjYy(&`C<7w1B>UjS9YZOzz%kEBV8whnW$1H8*og6;v;kA5SPyy!8pacCf|+ ztUZsdy6WuLBu71k+jCMp2CO}wLDrsgU26-kH)$QtK9MJX%ke%oHdQ6-nghjK?1lVA zuA{llM%_wf*E#KhLVon4M-B*XwhcOWc75BH6Xmz}dtcku7j`I_l5f`=^>XusEvEfW z{)P?~?(MBQUG^P0fA+k53;I5M%mOXK$S6%kwxrw2-c;u3F1HH*kQ%NShR`Fg+Q11@ zd{nL4dn-Hs)K<#HWQwf$AJdq}o-(k@|jHDEjGjjx9vR?|%Par6}HVwb8`gje)g zTP;>Qsy{aYqt5wA7O`XNsq^+fc`NZ#$hwfg9T;`6ydaPwE zC~eth7@~#hTHCs++z}BMGfoncBI)Ivf1>Ie!o@U(2FpFsA$@waX1FwIzVCd+?J5@W z4ohY)4Syg?(X0~QooqVb;#y90k93*sAaur;%1dJ z_*$rCS3-+s$vexmz;g6p|K+^FF86OJ&t&9-K3?&hs%PxY;StI(AyM^kKu?JQ@# zyJcF}t$4!q?vYbpgRv`n&25x+o(SLI)<<;p&JSpTWsXJ zM}O7AfR+9|^njHdJKfN-P}`Mx16a3-XR(#~w91r)%N=@a%DIJ_^{|Ei*ntfXW!YhO zlwyqEKlyO@A$#alWd~ow-N*?PbbUAX{NsCPop!t^epzS8+-zx5K>lnj;+?ZDRXBP- z)T;vSzrE3L@cw*?gyXxt*@3r0V;f9sUC!Y8!MU7e%;pzrYLOX@HcmqCs)NlPE2Bq5 z21Qf(?mS_T^%$K;C@1-%9*L+e>KGdq3UChff(t@4k0*zR`8ixsd9B}uE$}sEWC=R( zxx6?qLC-bJhZ+*P_pX)UrN({MQJC9NYVxwj zAKSrI@oH-*#{_`I(IrC9`^~z%`1w->O0Z;An$TnSS1k@{{4Bu<74NFu6@_YJ$6hoL zUJ6@yJc|?DomDw1cJfHqC6SVd+4eo=RjtNL^xp6AA}R0wtfrM7p!YNg-+EXLr{8wl z@s<12k)(!#duv;&VuoYphr=V=8FHS)jLAbI2LxRLne3)Fo zmdBa3&&T#+HP61S5>`o*9e%8LT<5_bl@i3Yt>;QBaEX;?MXEvr&)yk6e@E3{wA9IO512gue)1|BQX7?R zkZsT;H972kqcl$Q!=%sNuSm43T;i0}%BbAYm6{pp*Q4@Qt4@l@{oK{0kl+v!VzDL3 z-7usEF8{38-SY?Wru9&i-RuYaxJpqWjnK4GMoJV(Bwv-)@tM}I)m^&t3MkNVEb~QI z`$qm^m%E1@n2#T9bk5fE&>{>)HITIIpP%Wi^myTThLNe%U&x8K_E=vMWrmq&%3kpx zxtH&y#Wma#;kd5C32W6JHM6eEB0UedM|}k)Q7@r|R=Y z0hjkl&=(?hxqC-vh2D-~qFk#5=Y&{9)?@9XiEO@kXV8bm-Lns~KN_kt5_TL|I+3d_ zCVR#G9Y5xo;aXYs9CDU(K*@IUHGzi$1#PNoU37Va%`AMF!*dcov~v15EGvu3^Q z0Owfa#}!#mvwF|EO`u|5JN-F^cd2<$);rLc9l5@@maAO4i#4~hib-x@DGly1&RU~F z)W#l_kyOn$&)8|+d_bEnq5t|_4ZFqVq}nh`?HyK|!q@UF`Lv|aoj0w0iVjU8*)$v> z)_~@Nm0-LJT5+sN)zJ@~J9n$}_a7f<-g~Vw2K99i-+!Lo23F+nR%+bUFJJ2S}0sWtz{lf3`&V|U2BV|;!-1=jE{_az(t+xwEIF3tE4R^)g8 zz9QeS?)MdWq8t`e?bv^v=8@%OD>fk1K1?^r2cL1Cn!A=FFLIa^wT-mjBXgN%lVy6# z5-l->YwFe(aqnqj3TbLhmC%F03$g@^L3!&S%}7Cq=1ia*VkO>H=k|>>&~XKw7=Ol> zKu;YpS=*K+kp*WosPR1%E!EC?lgpD!r$#%F_4l)jX6*>VNNyG|_Y9F7EBQb@eUf?C zz?rjAUQ4*Z-H>#sEJR8`<1^}md6vQW7mZfs>{I3J1+T^vskw7AOD&Uqk7%-1nEqL; znesr!;+V)T)G|nc_WEO=L*$vf%Mun-Hib}*N)GH9D{WNFj zB645*g#@g>d@IQ+UgJykggmT^zY%YB7<1^FjHaQhzwd2_Yx_kLmz9s*T6g!x-6YL3 zFGISc{^;&?p6}xJ`kZ~~>xC-`^`x3>)}5)0&wqNZ^VlTVm39Bj$%Q>0cRpC;#J}Wg zdV7rTW0|M+JDG=W?YnReqvu8E<6PXDVL=a@KG+TOc8V$?Snl@DE=IY(v0sQKq#CqLe2ZvLgz zZRhO8;W7se&n>(1c;7KEpGCIE9FOEA+~k_fxt~~O1wJPFWVzccaYY*fFrbrw}Lw%8~S-~Q}i6?4f@_x)<+jV||z*HtZZ z&1CQo6s!wqq82d}%=iO&(a~AN#eckCwEk72?;P(y!5ivoH`T^7`m{u;1s4-9%{z4G z*`lDU-K(_4nq^$dh?XJVB?s}$JGTyf*)HaAEYSetj}Aa#D;tOcS(f~0nFQ@eQ=d=9 zJ1~`=EeVx=tt@n~r(OR{bUihwnIou2@^9kcn<10`ADvhUHrDP+RBub`H7imS-enJ1AN%IS6%T? z^0_1f_cdsja_pgI(@UBj3iHd4Z-r@jf7mnL#m0Tf8SIl#)r`F1WV)5+8bVdlOrhVN z{cy>Mt}G!Ein44>($wt}uaNjUE*kR4;$lgvqC1_Gn>$D=IQcMdPwh~*<gs ztMvNrX4p72x>icH?db_;1y_%LuI>uC80h=TC?jmRNo>iy&U+6nH1;MsUS@XR3RPEh zAKucgy!VJ~?q%bbaoZC@=DwbHawF-a6SKZnY2^b)tB|C5>F10>n8R(WEwZ<7Dm7Rs ztKKGwd8(k-vtqIHsEbRXq)@WQ3g2k?M|EJXS&++}uov%r965BZ_N3jw#C-8VX63uQ ztVBgm$&&-VLBbJoq_=cwF_}}QMGvQ;#9vRxa zDBufbX#l_PQH6*dk3Jx2`ADL&D{;AkIvzq`Ah%k0mG8+-HiEqSebqJ=FpH?c6MZNtHHLm`hZ*5zL+3;CU8%bQ?s z9~QJK2+lL|cqaK?c)wGIaD56%%G_k3b^Km~m7O7``CW8_i#B9j?1_;>UU#GRw(DUe zMISv*EtR&GJC^mR+Ix3dx#a#}=Ju`tBMXft=|?hcv4YJhc~F-EI+!I2z9??X=boBB zLKE#0Gkq+Tj4iX#t}mza`@K%6t+KhW<9ghCHNNQXnkMyywHX;#tT)AzN#+eZ%0JQC zuQCHJrlue9dm{S?3{^t;3-P?f#S%JNx>M7I8mjwr&{3-rnur>07O|fwFmtSKPy+mNqGD%9rPaviW6B zT~VnfC&`yu>!03FOiNE)ZSZKrx=hFTFtyjOl=dV@#-HA3-V|HQ*XR=|I&el0`{t|j zg;17e$(;xRA>T6tb=Nj&UJJFq`6@ZD?D;~=D;LR{kKNZv`h7_LN?R2^fUl8GKB4va z^gy;(u!p*QUEhb+K^wiby)Dgqv{1NY{T%+qJ<*rX96DH_as;KKC8Uqr8`Zi~F0gQ~ zEW5&oP_lO*CI1ghkyjT5Q`T`pzfDg>+QC@uwHGsV`-Pg6%^^!pogyDjNlDzKWWUP&tsdiHoYx)<=MQGoI)QqqAxr*GLokz-If34O2~vnerxukO`~5X zd*3g!A6T+I%Tn{WmjyUW+)GgUaKweIXYUeEEMK7d$YEK-al_ZQ-W2xwn!9Gbh;*~- z^Ys0iAinSjG^sae+xb9^A3s?+Hu+3%T^HYbwDF`nwyH|PB;&;iTawY>xQW~QqlYO6 zim?Yp1C}{Le}-h)cDk2WncZ?Kep}rBwLsSGWfqs&SUB8orrr1~v!^ffrn_3zm*&77 zDHEu{r_q;`%xvbaVeUSVVxH6Bj=gNL(f(xgRm}3kH;sox?K(f3U(0>sSKH!LH7I2K zh;SxXtX13oPGb>@5Hx&mpp{gq^yo@V*m1ty{#kLFI$M)I$6$}f6j(H+KaD%Wi5Dct zCz~ap6mWwTS}#IAsF>wk%Qf5PcS9!%>o(#d^zo*a{2i;cW-cBUm1n;=b&ND)F@j7s zO;w_;Ap{-Wrxx(meRt$l%mrHX=Kj`KPozX>t5;v^!fy*cSllr>v_o1sVMV%IkHA>k zF%5?z_f=Y391_+h>j_8=H5mDC^sQ9c9-l1SdEUDCRnVx~>i`K>aq;2q+KK{Mf3Z`T z_~GSzcAeL33TU?rn(o}s3NC69i;637f9xzl*dRf3l&Cr(H>59Vqpjd9&o7SMqxV#| z;w@Z7GK;SY#O1!M(44E&UpSa5SD1B%pYe2PK7NOSR6?>4Z+jUe&IfGNi^>4OGp4fm>op*d3eYlkwWI6C1( zCa$5Z&ZTGT2r7pCg&=6Rd4ex)#DGK;O;AaxY(73`wmjwpUNPis=Y+;td#g9BY=ida zMjG$EvYXexl)^9ZVh6lAAm&vvaKNn@H#g~)_9f4k_nHWx1rPMpia}&?$mo~1!xY@W0`ttpu(7>{0*MCm9s(}8q zDBL0R5@mJA#x7wJn=tRQM~5-P{b@~Oeh>8VlAK=9B^$ftdR%L(Hypcw2`RPZx+EpD znogyfo-xc_p|-$)p$A_bx7c=61w7vl`#)D6@>fw8^cBpMBY9_YeEDa$N0Kdyb81cP z+w8K=smHHT?}^dRPH0Saa;Q!_t9@A0V|S$Zev|4Vboem7EsAgqsJk%dAHtBiIN&l)JX=!Df(gng1F4Ir6R%DM1dNoejeV4zx5dNr3k^4%I zC_!b_MQU#OL^-u?^2W!FEiV#maHLBK{7V|QiCLiXG zmx0=@pgy*b*!%9l#*Z!)le{6L5u8TRmY$FZY5g>>g`)eUQ>*D-G^biSyz;F7yokfA z>ogj-+_-0*{d~#NOA@&&_57QU2Px{kR74MgmE5QNP=CACyO?Cj)nmiG%oQySVWwq! zR%%dc8`?cVefh{*-?Up^((P_m)E{BZBw>?9T*zamK3~4`nrJ3+{i+M6-PtK&#nid zz{p_W6g1#R_qZ7-uJiKE4!X1FQ~S!ic!6b+ZE4B^I9id+T(|qmTV=Du%nJ{+rhUcs zN<7$B?&a^H=3a!RYzm*S`E!?ps>krZ{_vPLKc3o(Z%icou)6#0R+xXex=TiO>w`tt zzd3LBUwnA{AFl55X7<0V?i&8({(HlJd;dL_PfTMr@2Zy;zelaD7KZW}woTsb=2ep0 zahN!8-K0feLgORwg>f@ePcA(H?7zRhN_OX^$2&&(v}8n+Z3?shV4OFan`G}lzNcY$ zu~vZ~#{ERrK#;XuQ}GGKQ>H%ZGCgXZn#bm5njQ5jGq4D5UMDWy9kj$JtHnUB(uXnd z%q81Zqj=Sellkd;yF<2LVtHLv5dFd}U%BnZN{o{Kwk+z46T)BCC`4CdTg1yd1m z?j4jV_smW@dPX!foy~G#--pCx2)BB-BXo zB|Tbnu`DEYK`>WH+^TiOtEy9>$}0P8p2yK78?Jtulp-EqiN~BeL3V#?FUF1hP^%|W z|HLj^-sY1dlN2UZ{c^3GsCAD-n4}f!Df_@FVdrJ~ijT^u{Eoy_9Qx`gw{efly4*fe z`-I5#uMXX2_xd|@i#E-1t1gO|e_>8&5mD76Ro%c9D}Vi6B5TuQ!s1+~)=5n4Nz}p8 zCC7BioX17hNmD{bEM0oTTy~n+FSAoS=h3lzac}iD;o8O+=jsdhy=SlZ=j z&6$HX+a=pBSzqz<-MvZ*d|~J_OL9Vc(e>nY0jqij?McQt#^ILBA|T7ywRxNW@VUP} z)O<)!(qCS7_4Y5F+J3u+a^`z2Js_Uwv`2+=*$-~9_a#SSY*WFJGbWCH9;fp6T%!!_ zm7#jmqHhk>y6)nviK@xjTVHi-aYnt*wzFSGjb7}EqDxmEJ@C{kWAV0|Z{Jj&_lHGgE^1%AI0-xsU)b>&am6u($$H_7+r^Q6E&&c$6a z@$2NH0=Bz;Y3V4WP8>%c7?eN0-g=_$#qilz;FO}wH@K0Y$A8v$?%e(6{M>~ePIniV zW7jX_?&<&V;NFq>V^Lc#bWa#>qU1X4yA?ayAH8#P%$JvcZl8ZMOuhfpyp>^^$HFRz zMp|E8B>00CJMmcvRDC>nq|7IaAh+nxciZO6ecifPb$lOX66)LJ$4<}2oV`4FhpOFW zY$>Rv{fci)n2i^X6~n}hr(qp^L=$adVy*El78m(QqWv)v+U`rS@$NYOf>y9<7nrG- zWy2?SJ66hjy?Bl>A*`EE%lb`+^U9;X$!iOC*@%@YSO+|GbEK9QQH|!OK13-887?LR;~E$9KtXVvi-Qx*o$+n%@%w6Uu~pzG6EkT`C>(pJ z(eSF(LPF6XE9X*f+40+(GzLDns(R22uCUjU8;kw<;5&<2#fAmZXXtsB#YQNhSRy)$ zi&IQ9O>Dhs-{inhi>)_7LA=Gf^zO!$DCnk)KiJQ%_;eu(x-IK}n}*HNnVaXQ;{p!% z!Wj5zI$0Yj7ryaJ&VCQxro0d-^)^sy&Is!EJ|7Xg&o{N%MY{PTSy)NXcY92`@?xEi!*YEZ%Eq^DdJ`z}Z{Uaxd-EI2h`WI2^bt0zkl8*8vMfK8( z>^LEZ6_%GY_a>}fc2l!vw%TA!LG|#Wt5>20(b6p3#V$gJlca-^jT2^VSI)r@rBxaw zt5a1EFg$8wZmTll^Arm*G42y?)(Ni;%xPmK(nmdXs0JB3?rfX=VN^E0_$jVgo{%^) zF5h%59IH4`bi?$>vazwM%y1_2a>axa#7Kz=PSm&}ctkX=I5)fF#ZIT4q3cwGopIMU zauUSu$v4%X&ZKmlyw)G#;K-S`echIZ?zLf5nuLF8O-A7EmyF|g`|^{C#}=B_cS)z8OKkqyZ+-QijJ33%$fMhaas4Cn^xwYm zPu1Az-ouho%B3VpuXv<*H+I%V3*^3_$*h_sF{y=+fU$IHd=@=-h_OY~vY3#lts*|| z?JTJ1@w&mpdU-&t?9sIi^6{y$($63rGIZ4ht)gr#U+Z?cpf#1sh?{*PAm_9()9W!d zKq0=Aa#`x2!rr6N4ila`T6g#>uO8c(qus&uv00#jp7Y2~)y3u9AAyEL?e+G@hmHAU zQb}v9$w^L;!L5B2p0@k$<`1Z?>)3E>!L6(nLpu_jJ5Qq*jYuCi80py7q8M#TdoGy~ zcClCU##i@IaqU!g1EHkgp%#5)e-dm#&wvw*ePrXyCnTS&yj*g3{&VH5cbDe2{+Xym z-;fvjbl9TGw&&dQw#)mE4CxE+iEIn0zr0~InH}4-SKm$FIw$}B zYR+Z52RA;SIOgSPytCl57`3Zku4zB&YWGP>N8gPA*8Vf9C(Y7_AZq<^wEu%UG=t&I zZ*8+M_uH=5tK2eSxmEDBWY*ra4jItR`STXGZBI>7+XE%*h<-}vEcyMnKB{*P9}Da= z+$Z6AMDuLu6=%hOmu_v*JC0}sM#i0SKJG0YcIwSswCN}AwVT10lh#WN-#aN!9Cuou z{PxYRqdTKy#b1ogKK3>4f=Latl(|UyWs)5qENa+&_wanZqZ`k@eUg6v=#pFS$9(EO z&Z%B)%5vL~=6FuP-iQ9_ezblb?fjkaD#g2R)hum4XRiOeeeL{BwXq#SgA%6)dp=*3 zV~6qOzqhMo~(6#@X1-|VZPW0KYYF@7uV2|9@C#0vsW-|#jvgXyQA+P6`S6Cf!91bIN(;@ z35DF&c~88ibh}-z4>!V(!;18`emVZ&^5TKZ6?R|K624&d9xQ&5Wp@|+Ny-jWrS-V%L|ETcVvwK2c&SJc;huj5Y2C?{SA`P+_ z2d&}C!ZXJ!az{@#ib@POR*YHs?S0x<(!Wm#Un-m?Es9-xb$gVsaM}3wV4T(k{rt(Yabai> zH<5*nd8%Bwci4h6If*h2-Q8i@jKlJGw1%Ye%vL%U1l0188}pZ{A#j zWNiGyT*C05cZ&WSbBTXv5s{21@os(OUF2biH{{*90UrMOA`jkt;+HuFvdH-B+9z_E z2$=FLjqu}cVAJsWo}37pCvX9r8#N3d>_Eo#t*GHN-nAq8p7bzUxEpP~2P=%q)UjeQ z0)V$I)1MVUX9nT*m(!V+%y9Y);^!63Z)>tYOu_y+ed51P|KCsguV#P$oHXfQC#~bi zr84OL|2_xA|1S3iKe6EKg*kpYbXIAa-s8Csk$;xeR=c^HJk=m*~!Dno!nfJckC zkucMM6GmJlP<0SMVnBdGG5W?Aj}oMS*v4Q3^h~T|<0*coVnBRnxI^4X493&;Ob8=@ zLx2|}@I%}P-S-$~d}c!Yl|7TnjE&Gt$>Fc4{|+~knh|-12gHSNgusvS&%|PAG*wQ# z9D?%smP1}HW~jc|081nwLih*Z35LhSKT-bZKg0fvZ89Z@Y4(XAsx7bb`Vcv1kiA-Lif@&6vfkJP`q$$(LW^}m$RzZb=?QU3Uh6aJ>m zAdw$^DBzq06R@*`SI88ghD4y$h}00e8T(r{Rw1<+G{!cxaDNV+&1G@$;CLL~3n`?v zr!fO~O*aqsSB?1haMKY@HQ&Ft7z}DqIG#LBWM##Q0_}q?35Zyi1Q;e7kO0>J5Pn?g z;o+cJ=QSgU3;}8>mloy)WQjD5h}&V>J=GjqGJ_a2JVIwp1zQ*BLBU)kGVts@{X`)n zNn3{d)4(NGQ(g$?$P-8&c)8H1ysm^uL7rTxQB$cSYK8=ioZ*J&jR*`JO+h1pw&{0S z@o?W|HT}heA<__oo)M(P4B`e8@rE<+{iYBgu9@@Mrw~X}^gZ%$E{8@9!wEw$1VK0` z20}ybirsNs{+|UVY_|r z6@uqs@Ej1t*bq1}d+Bos;&%dJ%z}Xo&L7^84MCVh;7hXwxKWEz z_!ofZeh_~$g9Wb9f;ufANH`cgr-f0Y*k}|=2Qc^s(Bqk)Cr=?V&Onf;1n}R>W`%PJ zo2Wt%G`kXl1P0g~8hfKB{saWcWP$WSTqr#_3*v`RsCrZih#_;zhA%-R7!A0DXMVu% zr{8jS>&1}8IDUK*jfYx6T6xe1KmfuZKUjq)H3*WQ!hmN8#sHY|hLE@+)bzuQ1w7Gw z{1^d2Az=|LPIQ*oZ1Fh~l5?e`Wn|^#73R&yD=I0gsH&-JXliNe=<4Z%i}wu3h7==X z6VnA|3(Xfd&3O&~UM_srgdN<<={0SKF_3 zbar+3^j^Pl^VaRYJ9qEhfAFyX5y&bZJOWG%#0P|d8s9QLIXMYIK#nnp4Sq22YXmkL zQ1An{03-+rLBfy-gaukC3eAGVpxKZ(GzXG^B%!&G6eJDFK(de=khKCd51J3*Aw@_D zQifC@RY(m|hcqBfNDI=2bRb*cIX<^0d+!MP&d>A z^+MO78_-SY7IYixgYH0gL5px7dH_9y`k_Y{CVT?^gvv*~fOo_3@Lf~_ss?UE%|(lW z0`@~OU;`8xorktUEkm`#f7_Nocpv)D41m}R#S_1NX6qL{ikX9?mlRw}wA9@S? zFM(3#f-*e`N-O|K?=aAbtw5VnAVmv)em*n`(uuUiSD{sHm8rqf%E4=GbalQxPd(!C zXC@nr#ZOqk6k}Z-Jif}pSiB0RAV^&uxXLaPZx2G+QG@Z`NJPrURVY=2fM)EY3u^p) zkpCN?#XtkSUTA?_SO;PFO<;aLV>C(tV+^VUEP{rlV8|{~-$)u-WVXl*);IfNh5#h? z#SHut3DtrSzqY|_#o6ir=EJq~zb2#cpZn*d2ENP#F}qB@Kv}?jpvFjnTCmQ-R7em5 zvL+%dfX0~c^MSTUS4i3&%+`7UiW~OLe3+)4m!0a)@t5-LI=;0-NCY>?hM080V5 zBLIB{ZO>=O3WT=+Ktkn1asVF#==p%H4B~eLwiDVJk_0%wSASsZqg@9HBz)Ik64nPNh8UPu93jzAE1-NO`fRrZ! z2>=)XkUXJ4-fMK#4*Az(&dzfe-+QtPmRkWdMi{`vO=G_dO@V_$n_jLg2Z3nU_;lcwDuPS|4F%@6uMw`n(s6AnT6 zLps#0uKRg(#(s}a)E|?V{ zPc&d7aYO<$0Mh&U)drY@AnAmGSq9^0pP!!qXL_LY@L--20ph`f*$WlSH1Gh2a7zU9 zA5#D%U?T3BoREKxWt0DAJkbQanOn}{1h~^Ufi!vp7^PoyF9{TQV4U599?% zI3C>JP2)t;0)FAxjl~J0{w=RWJp$e{f`)gcZom`3MF(V4GRc%kMpFKTpZ_oA4rUil z;Lirwi^2SHIVf2~hFmbCv;46X{+90V;`lF1=x@`Tu9cIU!2I~HegnK31?n)2g3&M^ z%nxH=0ay?gf`wrb7z^WIQFsfunX)8yTOZLcX$cx0WXC;;bpKFyd3t1ec%=FO4t`( z1+RwJz-wVD><9b90Wb{?goEHGG>2L;|31`7O;A}Vt&V_fvdGIbU zi`@h7h4bNk@P7CJd=M^x55a|S5nK$Hz@_kExC}0bE8rvWQTP~K2_J{6!2Guwu7OX& zr@-v=G<*jB13nAa!S(Pt_&j_8Zh*o43~&?N3}1p<;LC6;d-Q3P7h*Y z0$2zlO`iIiENS=iJfRo26b{fmep9nSFpHBCubNnO1gd>;%KrH?&4vjyE zLye^UH~J)m#7;v}MEg-W!n`M5O2WL9xO7GUjnAJ*GDZv&(eLv21FMXfKn9CLXJTiH z5Wxx37z{c)oF0w|pauoeI6_kvQovJe2Qp|;BA_g|!K?_ROfgISsT>v)7ZgEf@Jbe8 z2DR80BuFMA1_?0?5Q8klONm$JJQt7CZ^NjHji1UB1C=J|KO+WE+DKs9 zRAAcoz(Sztrb1!pQ#AA`n(5X8sdhs285%SVh=DmJ2G$fgYl@upJxUB~iXX6DU^?ai zdL%u7hG9(!Az~_E#8kkD?*WA(zJ=Jp^8_s{5Q5N#8MK9{iHWhXloTHySjCXBh11W# zliMO~gKea1z-vQDy9UKG(L9r%55Zt~ZULSt$TNj_rZCSG;h9(|gc8T27v*7Q@!VoO z_iUai&NJumObMPT$)lOe3oFetWqGC?&y?qx3NlE{^LXz0JQL3|6?vu-&s65cqr!8m z@?uuwxz%~51}_Fpo?DAYsm*ii@JwBvsmC+*d0`1WdLqwF;<*iYzGR+h$cur(^EE=; zKz2X=^VT3|R=;MJBYBHyyd^e@vB?kjeDT)Q{tEwXBL-N_n~8+Cyv8H`0m<9=!bAQ? zyG4-I#qYaStU><^6bAr0bss>2P>Umw!pJU$QK44coJ`+l()PK zqyv^+!4Y`+$c`V73^j-r4xZeRQ4sK$K5F2{OFR;K^${P6PlYs^!-tfmh8!%ywx z`hjyIqGCTM;0hW_>eNa)vQkVTlJG_*BqYp_vO~oAJt=EsfCm=&HE5>3fgDyCJ{$}N zeZwL+5kYinurDnl08Ax)sa!7AKiD^v$_?}967|-zHIaNGK|#lF14f8=4KP6r51?+) z!Q0XNIH2d;fF~O1AX7wRyrHQ9(Uf3>cXvgCdD6iM0I%`yqyrQV31Jz5G_rV&Wz0|} z=xq^{JBJkz;ZFldOE6aOqjK?pb~%R*`fI#_9)W}p1OdPESo^o0hdT6>PX-1%XIxXn|DFciMBnteCs6k3dQ38I!=LM2J?|Q^9~A zPt-FsF)^9mdiO&m%40&@BZM<9`nf5jOQjR>I0`H7A~GDMn(UvS8t zm|t;5CZIz7LqC zpqBlN15{x5%r7`Hfe6aw=dcut322{x#(}eHeodDI#PVx=MqnEAYd%OOMo5?Wb9@wI z%5UkK{LZt10m0-~`H@VFK@;|Ke1OjASN;qr#=ptRh-my9F9u+F^Vc*CC`O=8{hS6F z6z{M3HK2eOUcb>1jenH^*}w?t-hPq+nPBjnP69g6QvE__MEFfN$Ogv0<(F&(HkkYp z){tn3bR<8gYeWJq@6R|uXYd=&kcjN*`YEg-5!Aw8afXE7WMBwX?brB>h$hJWK0n6? zcFg@MXG0UB@vmh`AsHa;$IoF+Kq>u#19S$z@@MoHc>`_fZ+Z`Q!TnZ70B7`T`2rmB zo#aov0G!FM`~fi|J@wCYpzZ!Ozd$p7logn&gMDM1>Bf2~eIt$6Eb4o(SX?}i3vY** zBQubNbOuuoHu#lhfg~D*;O|GKkOBfsC?tOalR$q$paF$oKnf)KlMT%OnPR$K4(EbN z?o^9xL^3i0XH==G+Ag-k2_xwt9g3M59yit1|2j&T86-@N5vGO+KaLRoy8*(FjtqVp82mUc(0648Obu*oOp!qhXbwOZVgMQxO`N$o9ydMuMTWNDr1X6> z21GVJdIfp{2BWy2KIR3x*};ZEJdiBd){X})1)$KkoB60$-;RU_H4)%II!Jc>m(swl z#2E}I3=kL$jKlFjw|H@T27~vDc%=J99)IADHvs?tjXk7&`jNkBc7NpW|5fqn+kLx~ z`JW_-G!H+pinP?fiW1@ee_WK`82sVW?SJAG>DGVbmDfuARP4Md*8e!KGg|qdu!@u~ zqWx1EYCJ9FA2fhB4g9}?)#=(Z!|Lyqi8sCcTUMv1YX4nj{|~ek>GXaS>+cndHwXT| zgV&!`z~uLu_3bWpUQhE^ZRkJB^?TF#twQ}%EkXuBKgbXn?;?*ssOGm@6aRa@{;qNV z56XM$qQr022pN0)!t1w71O9tn|3ZfUK}`p<)t|)qd-eHtjv>NEX1=I^Tdln9W19T~WS6p)U6`a8NGwUaW%4x)MAyLRva(vR{a5`M2Y z-`+;?1UmH!3=igzM3B_X+bCX?$lEm%qCMZ=u7RhY-md+m_`JaXr@8;vqnaPIO5g6= z$AmvhTOU~S(QurulVBM^2VgBl#;`5RVvpZ~1-7#nUDAKrq@DpWi zMe}oo6`SYmY3~U#5)`C`sMIrzrQB4yg;!CE6v}(;;^h(!c;FZ8bxVxpA8W%ekakU4 z`Jw*WX7ZZ$prt!n+nA=_DS7T;=J#=@I?8h{#`MTp>`!ayd)i#=jVGt36+Sm%FY%Wi zQj2?ZN^QRBX)I>_Y<7EyQBMl_9Wl>6D7gFivD~}m9*(Xui`#bYH*f3RU9#et(j$Rz zpWL}=iSM>wPNMhhw<~zOj=OQb;)N-kRu{3>J`8C;R^HD(TtT(C-iA3; z<||*+g&z3OaJ=qSVL^t~^%9HDrUscrcMr4OiHe+xl7*J&z3+7|<_dNh4pf`UlVS@c zQ5LhEi=P~hy&6)-j~ZApF9F9+)Upa8Ns82t-i=T=f3&XnDalRyjf?%VWl9Vt@;@|Y0bX!V3jp^|}(0}>j-3IBz*y_27^&Kub;^#6s7Q1b=Y-zw9|`uWS<8x8VAzu+TM16iq>Sob`&-*Dk6(~+tkvbw{8mNVnmo*IwP-m3Qh$i_ z)kpj_npQd5o2VxAex~e*&>(GNzv#G6QG1n5MaM%{?iuOxDeciO+^9vn?{w;0SSERT zVpJ_1D@C1!F%@AC1xRmJJKF0?uF^$cSgv-?VIsGwFrT?6!G3X3etRD(EjB!z<)|I$ zR=%1(X4;=(tSheJ(1;|gZfPAf@GbdD`Sb&WNKxiVrNVL5pWDGApy;9%k>#k`e@X5 z2+C7R)wOCgCN?4W9SDLWKI*FygS@|3b29XpLs|Ka0i&XOG{K#gt%>7L70?B62U19iXY2ubPvgv2M`p|8;|?1kr(6 zw!>ZhR`jvuD1MyIGGVl1c5#rL4u9$Uldgw#4rV$Vu+*FH7hd6Z>K>R$crL#C&6d(vkj+Uw*E+AXIvJvH(wtXo_g(V3@Yw9KRY{4> z>^?h^tIq@+oU$fN9IYR1m>xXZZ|&N@xdz1 z?OgLigpcXYIiCu5lUEny20XXxX&Q(u`JECjA<-p1k-TOT~Vojsb{jBZh=DFnr zEcF@NYn@duf!QhF_xMOVKQw$Eohz2?yp3bK7*nTeI$`KZ+kE`;$U*#BMoj4b1Ur&m zeZfkJ#14}uN0T)-n{2Z->hQx_9Fl$}>&(}Sd*pRW@D;kbYgmS6v7V^9jlOf#K@dwW z&6|yKoOeg8kj5u!?>RANg@$O7>(L{k*{5#B3DR&dpLxo~N0XTTD-s8<%Ml;#4|L`Z z$60b#XI?U$D__wk-bc$cSle22ihp>&n9Rj9T_J<3WW2krv1Q=?%deK;{!70U^RtS% z1~!5tRzvTN3vL#db$aJL6ZzP?xw&wau0^9aGZ!OjS*vLUmC34Z>pfet5v5K#6sIqn zy6t$1TUVF6e0REk&XTSNXvclRin|%OOiN+P)yA8O!GyB)B69cfjnemh6LHxM&6kWT zo;Gn^N|0LC@ofF(Y!;QQ;&bEzgxZODEA9kulU;(q0hF^3k$EXF>J3 z`y^{(OWvdxjZ((DP%lDj>eLqIrDQl7Y=}EaGHX~;@^PsC3RC5e6mUZ6@QA=#=WdUS zn>4!*=@XFiP@TgDw~9F>4Xk;w#nk7FA3pFkU4Jl|z%Q=qA~$s3N9V?Y{Ok22S|NY> zJq`J2SL3a7U}kkJezgks!;5mgriBxC-TuQD^n{= zZUwjAJXJ)I%zHn+tF|%Bd_ZxRrLn<=qIR;}S{s#J7B93>{hf;kYu?uO(A4yPRp68V#+cJx9ZY@#j*o)q{>B_`T+o-ps_#2j|y<42O z%BeQBT&GVQ-es58ryi1OWa_$Plxw>4`b)myUFl01`^Pbd*BD(98hX*0aIEa3d1b|> zgAT7kGH=9X&L51-Y$~0le6>4413P;3!k-S0A9&2NAKt>R^4?Q_;Pcj1*B5RhTAb`i z`?O)#Ewwm5YqqYN*Xqk=AFpw%E|_gw`SI<8QJ>&Sv!|_p(j{J^tE=1Izl-0}H;X-4 z?EN*2Q1#-~39XNo=-XBL?_X4jSB^tm0^jijN@yxMYP6p@I(U+Qz@q%caA&n$ruzq{ zH=o*L`EbRh0*$3Mt?x1!M+B@iTXQwk9+-(VjOpKda`@#EuEu;*sfyKoatq$YjGvb7_wg!FNI#v-AW6|XLDlU~BH$sXJHjN)p5G^j% z>frqO|Fm}|(5}>Vo(CQveR+AZjNNX>CQD^cDwR}{s-&{-d!;IsRJKY|RoVB=!+3;7 z`Uz?SE>G+}4y_0Z42?9(k+!u*X+=dx*;;L#IgX5iqcS=OwvHa=ocUMY-QK&e85-Zn zOrLwtx%XE6|5g7~s{Zx+|9=1F^F7~n;^QBB{;4bf_UntUG#~o;Q-Am28~HDNqj%-- zJCpIO_3jfF!S9G%)4c90=Tk`Ko+DSuuGfF}S?_JrC*OSiwV#LHa@B(mKOcL|Ina-8 z`fnd9W}f`@k*A*g;gzZU`(tmv=&kQdJ`j$b_oLhscmA+B`sgF3OCEfS_y8wd{o|wO$In0hn=drZ z`NT~x{Ev4%bN7R~r;nmHed(fOUwuvcb$Xy9jj>my|Ne^) zqz8AOd(W|7{^C7vHCA+A{?MH_Mtis3BKxrgx#+y_D@fxU{mjK5{mhf!)1~hFyy79_ z@jEV@y|((_k3W0o2bK4|VE);+Ka>8>yTXodefeTJLd!e<1U>VJ!SaEhJa!#r{n5F% z-xhrAeUR1smy1t->sjKTo(;cs@a=zl>uh@M{g-^{j-wJD^`Y}$^@8E{OOC~jM}Pdy znSSG3owU19AF+^qrG z({H@*l8RUTUE`(jtHW0wfA2?*U31rGjgS4w!{=O+{{ti*zUuKyu6-D>&0l}~{Oj(0 z>aQ;U`TDZ^ekC7#_Hq+_`So5w)_mmt>)ze&n%+~p=coDCyvH%io%@IXaQ;7DdrS8C z#ea1Dw@epMcfIR5&tLzArhnh3ul=<;{@M>;BQ`&A{p+s(_%Y}suQxq%bI8!_(>CcE9x0qbH7yF8I0lQ1G$0e=Zf7{M{9k)YtsKR6?5Df8+maZ1^#h`^2w$ zcf9+&OJrAM-}u2NwjTQN+!K4tFFyHt?3l)#tr% zNqBtY-7mcFkDX6)*c5{M@5|^b7II zPhR?}=l-**J^37k-4(t0-1}~(O_p08dzO0Qx4%6Ct7ISX%X zFDk9Nk?eBqvHOiz-*3Bgi5Ml7Q~I=Gy;&JhPYtkA3QyKYzWlCWFI& zawIDeQiW{QdecQprN5K@cbBS#;P?KG<{skc=*JIvvo}0_*^O6Se&-uP)>{217yhT` z&|jbT6aO<*=!VJB=dE9R{I;X_+yvk7_2bNcz4RT#&6mo!$3J>q@9)L@M=rbY?svcM zyoWX4Fdn(}t<;wd%r`$1dgHoV`RqjxUj3bB6 zYx>4>$YV#p0LL$Uo8!Vq66jm$&pmqlnNjz{%rmzfy!P;|LgaEJmP<{uYK}ehL7F*;L+8q zm3QBE{?8I`K01tj_2S_DuY2~X_djscZI_SHZ!G2c<+&F<`_9=77u<2eeCIp8v*WsN z-}@=R&-!Y|!VD+ryS_5N^=}-#@7;dY8}41bkoqqV&#g!QLHqp+?kwF-sx9|^`+*bd zPwD@?t3w z)-$mgN|7BT2Z18C$w3I%+?x`WIfY#Vvi7rU!0vu_4cI+v>>3HTA^Tm>H4;2T_Pda4 zHU&t3c2F|FcKe~DQm-Eo=p=Vc>nb}!-O5^Ht~ zIQ>iR-+xhH%}Xj_e`%+0OSBrtQyC`j_*y<_MO`4*OaE7NWIrPoEm95 z)80OqVtBG^dOP2Cg)~hFb zrXM5^AvK4PnnOqp0J|JQYR)RmNGC5H&~kVzv5EN(AvOPxKx$6y)7Xzk zIW_0hy>nhB0_D_FULK_8)G|&&YEDf%b??O>HK!i=dxg|wULvIC#g2QiyqEce04nF7 zhvytZY7QYahme{>NX;Rn<`7b|LuWaJ)JXWC3lAYR02Xrysrf%bY7WeJ*o=xvBWqyT zb9)lRX5j3!Bx!6-N|G=(dk0D*a0gR&7EemEB@zIbc4b?<0*nm4xi7RO{shq8xx%@< zRA_ew#U?>23apU;Gaoi96#&^KK!*|u%)Y%|Vc*h)`p&o?m=theSTAYp*1Lu_+-t}i z-OwuMv2=7Q5)u-9tRi*`yn#DJGeX19T^b%_zA4Tck~p%ad)$3^*Y9A>5{ z>&D#mqL93Y#dl8zBX8^|r z7Bpdd6?1p7^zI^?q&4rX+f;RDN*VS>NY@-uP4%AfV(O=-h8j_`8{qH50h zOOvY2ubJ>B&S^;@E^eU((3W|F@&pP|n=^zIyi*s#!@&WqkUMD-vwLg^gV`|!5tRpH zO`?dAO2#o5@O`J5^>}IoKjgp)`T=XsM#~j4qtcO6F^b@dAWPWPW@9(56UE;HG^@0Gq5Ie&!aVp2}WL@ zpRra*PeQ5yHh@9dwQ~CwPQOHpb2e%PQ0qE<7Q)M^73x?R)C#-PP0hUVO|6Kv0wY9$ zv?pUfir1%3SJTxFc?+2Wp|Vw@CLin#QAPr-Fuj~wSC5x+YNkc>f@>YYhZQ_{%jsBe zSXPufh>l}A4qsH?C5fS>W9?~;Gc7yG^*qgb(v@%boaJdXskZ02ZpP3=J;;Dcm*i9g zJko*3oi#uuW-=*x0~2e*7;lK;)KYQT60t}VtBdU#Qd;R5G)-A+f)cCyEiq_jGz7yu zFkmK7u^ds7#a;f|fTc`qf;Cfy=(tdxF1y;kyWG%-x*}tpkL0K;O9&?WFdfy57o<1S z$yvR6i*Br}%C=HOmDOUon64myT)r4W zZ5C@1^DIo^CWo%C1`H*>w9LAqOswt*nCqrikaF9tT%n@wsco=YV^t(`EC0%+bz5k( zE;O?4YD*PI^VLeOZnUsod&eN#ieO7FTc=5H+8|G~LManL8>4tOmzs=+alL&Vb`%Ot)lFS)YH%xg)P!)lSqLIzTYl7{95kIaQw4WeR($~#;8i9YEVah=Majeu zQB#!64*5aSc&19fsc2HAw}Y*nO1}XJ{QgZLwzqO}XT9Oesq`mJp^iJn6pliivY5m9<0gHY(-USGWA%E^m+T!(qIxOtLxoN-xjiZs`3Jjq*w>Vg59;c|s+ zYaCKX6&+=uX%toozj;w{r$d$Yazs-3rmm1`@rC-Nx>g3|^Jup?shXzVJmYU^$3<0J zsb|DlMz+--X$x7q)@z^TM&xKz@3)NMFc6~b%wsqa@bzk{T2uL3-dy z2d$Qz!J0xC#i}pcTBxIXtXPd@N2!S0hC^)^>dhLmT@h9TzG1{yf;mUEKKDjEHaX16(*wv#*P8A;IWBv6rX03~ zi}VnyRN^kJec76}CfS(Ih&qi?w5$*2>da_}~E%~~ts25?BE!JjjL#)&k#X-!6 z){ssJM;1_q*0?Gj%YZ^*B4SAf;F<=dQzmn#BHJ>K99%oEH5lX_qQq$Z&f1K3&gxE@ zNVcZx2|v-s>m7}ruttk*p~%}S@&O;~*)^_FJm=Cm7e(+zB9{27#fG9*C@PPDb#pbZ z*&NeY0^PD9>w>A-XdIp33!&BT_|4ryx@}1|b#*~M48)o)9h@x5wkDNGi|?1KH7MgA zO!csD)gPSkRp0T>F@UYuebslI^Ox>XpOyCQq-V5$mfg#F)n8is#-KFkYK!w=Wl%<@ z@T0U5XU|+}quQMVEUiCcS>9I|*RxJDMDQm4!GS>p0%1GOuPZujMQV&Mp zhNfcXZ8`>RHD;}xV2P<_9HA63&}ha>$+}Jn{0&#vJ6db=6*d_u&r`TZQQ$}Zc>{K} z`($A#B-_Cugygffv^+2>5Mwwk`t%{kC}?b0yu4ap)c|)qrIvU3<$4wEF$y%x&b5Pj zGo6nW(YT`KMOdAQsqqU)@K{_r%0mx~`C%|xTuz+cb>@tZeka%h?6JK^FGW|cfR#T( zB=)i$UhVQUE1#JalQhP;ki40c9NrR5mH^Fqs+T*FN#7cpvNakf-R(|sxHiIT2<6dKjZV2?&-#L1z>^Q zS6kvXyaLbn>;yCiU+t&^xUN)S&vmVHAuB4muJXi<-%v^lJM#Z`{CC`;$D5yg{&tdVmvIEhVZD9B(OR^Z+ELzp=uM*d;{|{!=&66w=xa2 z+d)HyU}K??^SZ16BJHrlC~DhOmWGOK5+!C$XV})V_pm(e^QD?J=g0(teh4|^Q{D|w zEP$c8-3=ol>0W`SED{bEWi@ap0?^=uEFtBFI%@6}MGm zc@?JA(j40yq86I;LG_Wl#>-u}Kf7>~@o-bNTpT)E;;GQ4^`0TyyCuUZk6N?Xe| z{Wf^C(wX7)qLA{MLTgXE>dOU!n3}#hsIZhde%hXyMVYQlp zV$c~4Re^!XwCz>5-nDAErL|;k#`~H`Q6+@dQ(G%ET$s3SYi1wm!q6}nl557=uB{oSUF{L*)k$!(1|Ko0M{uWylN}D5l8Lk|pIfSUyb*O71o@b%1Yq*|?v-*M>MTV5{g>%5<3mD=`y+|!<7Qw@5#Q_;}t2c2;sW_%vj>ecN zT2`U9lA5G4c|$sr$3cq~8@AJ)4Df;>S5?lGl~Wf!udfha5bvfuS_|(l_uzn11&{Ki zx1*t|Q-Yr&4iJ~HF1Z2clRLq9*$>FH?Pi_Vr{Xo`WK`3Uz*(uf{e4QC?4{CcQYf3l z9<(?JFwD{IY$X-R&5W@y52cIaaA>`7sf7ZNfA1nO6{X_eXr2$8O(h_nPb?5ZdBF7-5Id%I*q+y zt}S9Zw~(Q1f~{xfY>siGw;ha|noa|L#`?bFoZCSk_ilZEWt?+~ka||?dpF6f7Cqo` zyMZNMaK096QNyAv&CG zxmwFaNuBgI0*GvDHtZULGg35??7~d1aP^?yap$e6q7R*V25F?PuEm%DZM1jgy_VOU zDeK{anoA6ZPMa}KmFu9xB?R%L7zl+~2dM89!6~OgLu$cA$wRYjTJSj0Z=k?A*ZX4{ zF$U2kr;ou@p0 z2XC6~wDTE!kTd!V5!5i|bS5Zna)hZ=hyWHcOB*}LFa(c@A+UXM&=EPT0mDU(#3)x3 z%Bif5D`e7kfvS!*i`A5_D1eJtGE@zV?2K8>+8EJI54t%+xkiqCp}61~X8WW~8hX); z`?E>Mv1+9KARC8Ggi^|GpqI80jRcu8w1PcxomOZX4qL-JQ~7iTe~GR4`cSy+ z9D;T}oER;J*$F1EHjU^6UL*{Wkjfm9_q$v?)K!-Q3Oej9X=e--7|TBYRQ40;hna0dHq5eS`up2QW#hY3{I+MibcXUwa(|7Y&51ESu)j8 zleMJN3V++j1X6GX;_Jx?Cfll5D#NLBJ~4I-*+PApg<(FVq2|%_q#wdeSUWN7o0?It zpJjUy4rk1&SOs)Iajb(V$5K{+~iu*syN zFcB)HwktVHQTbvaT7-tPcCa0(C*@?V7X^|7V#b`GI2H-H2$NCL$S>6PNSd!J&-j+? z#5@vFeD^JRWnvzQUw$?$=6I1TEd-4vQD1}R9azkSa%6j_$nbd4)Ei`?d@f^z zY7J#4Ps=eSJTQ^sBt+4gpRo%#Wnxu@+!J^7NkF`QF#erD3ga&Uzz z4;vkmxl{l#k1@~raE|Pm$2}sxS|p9EhDsK_`PHhQ@^WL~r*wS2bxI%3WgVe0uV3P( zdd)WI8tUE|GE6#!R5>kM*X658SOaxqoGX_wb$0XTM8-SkgR+(2OfC8(w z&q|&7ms-{k1uSbkh|J^FDCHa%ie0{E>g`xoskb|;rP*assJ61UwLvpcm$N2!%Uv3W zdL}chferlBN!mueaT_sY7K4dDlS!A0rfMx)&_~lWrU#~=y=>7#H{zpXk#IR`FuE0G zZa@mD6lWY$5WmdG&9q9TAE!MEi=8yMvtX!u+FXZ)JYq$4alZ&!S;S)IwJt*lL{8fN zQc$8nb2-`4m~}OMUYjxbEUj`h=g>@TGYsyrG;XsBF38DPbv>J{(l67XhqoIy7=;-m z$a@BnV(Wai9_<8Yy5vHy(OPm=XtuJegLymW23@$Bik<43c>`s2@iwH%X;`))MNq}I zHexY%)uq;&E#)Yq!QWI6VHDD}F*fTFQz~zH?I`3LB)lwSs<{%Rn|YC-vF%Qmnlm%# zo^^ZF^?Xy|r?h%aiCL-wD!h)<3bdvkGYbxjimjFgnMWN=G>Um0VCWnpjVq0oPaCTU zJS-A`Y0lE+xDy3nKTC`4PxY->Xgn|#X&Ma0+PK+fh$pvTeNAB)pN<`-RX@>4Q|2=n z&6Blm6IX$#X6F?+$>;q2I~RzgAMk&}ZdzD-(dMX5McP_ocx#Ypv|aOHlWGpy$sjWk z2|5QpErD4EnV{XP zAmIj~trF8(81gA~!P1~OZg)Aa%QIJ@Wo6TyO%=gIYm=%Nywqm|?}U#O@_EWTp#r=` zgJ%)4(=YowSQ4_dv_|V(6>Ne*)%+NA1LIYzUdLNgXfF@Cn*>TX3{7)^A})9`hz(tK zGGe`&9$LC1nDJ0SrN8Y@*0AguJk7S<1?(g6G_x6A?~8>@T+ai!O!oYlYsF6VVY36I z=(fjs5>om~)QYncf9zUDYRZpK#vh)*C`hr}K4)oB9JsTvzL25gUR@xk@}O=9@( z>7*s%UZ(D2siU8aDU%e>Nw-0VYJo6-P-loMg=r^ zVNukS%QmuMD!`4XKZbyz111^(-d>0))JaovQKeHHU4XJaG#c{^)@i7waVy>Ku2Zd_ z#TYk)kj<_&5(uQxULjNT_1K6UD<~@^;AeF`f^tU063TJUqe|rypkHCtUQLv`Fuc~W zJ)Z0^HYV2u!MPtPXmq&|fk(V%{kZ1OOlz%D7km+6+U1kxHloTq+B%2j*-! z6p)@pl@pYUBSN_cg%@SSYURN2yFBlSjPVwcbm1v&9(WdNTGS*QL&z1F3{p*Vrkbg$ z+xCi6Al0U-i(zq;*u>j`KP>iDYZke zG3fl1czfJAbG(gMc7m+^0ry5p!Xn{@H&PfU^)OCT_Cc*yFmNLMNXkAyMtJ*RCwhup z1`sdU%W+7Pi*`BFvR`Zk(7X3?ko{6a0Ghp*W0M%jJEZ~8 z^Uh6nI_%pw6xowX08IV9D<)6)(p{op_;>A<-_`t|hd!-1OB zf%2>, 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 +#if ULONG_MAX > 0xFFFFFFFFUL + #define MODEL_64 +#else + #define MODEL_32 +#endif +#endif + +#if defined HAS_INTTYPES_H || defined HAVE_INTTYPES_H +#include +#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-7/src/lib/crypto/aes/vb.txt b/krb5-1-7/src/lib/crypto/aes/vb.txt new file mode 100644 index 000000000..dab133c2c --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/arcfour/Makefile.in b/krb5-1-7/src/lib/crypto/arcfour/Makefile.in new file mode 100644 index 000000000..d56deb85f --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/Makefile.in @@ -0,0 +1,43 @@ +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_aead.o \ + arcfour_s2k.o + +OBJS=\ + $(OUTPRE)arcfour.$(OBJEXT) \ + $(OUTPRE)arcfour_aead.$(OBJEXT) \ + $(OUTPRE)arcfour_s2k.$(OBJEXT) + +SRCS=\ + $(srcdir)/arcfour.c \ + $(srcdir)/arcfour_aead.c\ + $(srcdir)/arcfour_s2k.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs + +includes:: depend + +depend:: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/crypto/arcfour/arcfour-int.h b/krb5-1-7/src/lib/crypto/arcfour/arcfour-int.h new file mode 100644 index 000000000..efd7a0282 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/arcfour-int.h @@ -0,0 +1,32 @@ +/* + +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); + +extern const char *const krb5int_arcfour_l40; + +#endif /* ARCFOUR_INT_H */ diff --git a/krb5-1-7/src/lib/crypto/arcfour/arcfour.c b/krb5-1-7/src/lib/crypto/arcfour/arcfour.c new file mode 100644 index 000000000..206c1c37f --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/arcfour.c @@ -0,0 +1,340 @@ +/* + +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" +#include "../hash_provider/hash_provider.h" + +const char *const krb5int_arcfour_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 9; + 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, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data+10); + } else { + salt.length=4; + store_32_le(ms_usage, salt.data); + } + 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; + + /* Verify input and output lengths. */ + if (input->length < hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + if (output->length < input->length - hashsize - CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + 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; + + ms_usage=krb5int_arcfour_translate_usage(usage); + + /* We may have to try two ms_usage values; see below. */ + do { + /* compute the salt */ + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + 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) { + if (ms_usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted + * parts encrypted in a subkey, but the value used by MS + * is actually 9. We now use 9 to start with, but fall + * back to 8 on failure in case we are communicating + * with a KDC using the value from the RFC. + */ + ms_usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); + + 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); +} + + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out) + { + assert(out->length == 20); + return krb5_hmac(&krb5int_hash_sha1, key, 1, in, out); + } diff --git a/krb5-1-7/src/lib/crypto/arcfour/arcfour.h b/krb5-1-7/src/lib/crypto/arcfour/arcfour.h new file mode 100644 index 000000000..be408febc --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/arcfour.h @@ -0,0 +1,43 @@ +#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; +extern const struct krb5_aead_provider krb5int_aead_arcfour; + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); + +#endif /* ARCFOUR_H */ diff --git a/krb5-1-7/src/lib/crypto/arcfour/arcfour_aead.c b/krb5-1-7/src/lib/crypto/arcfour/arcfour_aead.c new file mode 100644 index 000000000..cff7d66d6 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/arcfour_aead.c @@ -0,0 +1,325 @@ +/* + * lib/crypto/arcfour/arcfour_aead.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "arcfour.h" +#include "arcfour-int.h" +#include "aead.h" + +/* AEAD */ + +static krb5_error_code +krb5int_arcfour_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + *length = hash->hashsize + CONFOUNDERLENGTH; + break; + case KRB5_CRYPTO_TYPE_PADDING: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = hash->hashsize; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_arcfour_crypto_length"); + break; + } + + return 0; +} + +static krb5_error_code +alloc_derived_key(const struct krb5_enc_provider *enc, + krb5_keyblock *dst, + krb5_data *data, + const krb5_keyblock *src) +{ + data->length = enc->keybytes; + data->data = malloc(data->length); + if (data->data == NULL) + return ENOMEM; + + *dst = *src; + dst->length = data->length; + dst->contents = (void *)data->data; + + return 0; +} + +static krb5_error_code +krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, confounder, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + size_t i; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + /* + * Caller must have provided space for the header, padding + * and trailer; per RFC 4757 we will arrange it as: + * + * Checksum | E(Confounder | Plaintext) + */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + /* Trailer may be absent */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Ensure that there is no padding */ + for (i = 0; i < num_data; i++) { + if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) + data[i].data.length = 0; + } + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the encryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + header->data.length = hash->hashsize + CONFOUNDERLENGTH; + + confounder.data = header->data.data + hash->hashsize; + confounder.length = CONFOUNDERLENGTH; + + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum); + if (ret != 0) + goto cleanup; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->encrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +static krb5_error_code +krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the decryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, (unsigned char *)salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, (unsigned char *)salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->decrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hash->hashsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +const struct krb5_aead_provider krb5int_aead_arcfour = { + krb5int_arcfour_crypto_length, + krb5int_arcfour_encrypt_iov, + krb5int_arcfour_decrypt_iov +}; + diff --git a/krb5-1-7/src/lib/crypto/arcfour/arcfour_s2k.c b/krb5-1-7/src/lib/crypto/arcfour/arcfour_s2k.c new file mode 100644 index 000000000..41053ed17 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/arcfour_s2k.c @@ -0,0 +1,59 @@ +#include "k5-int.h" +#include "k5-utf8.h" +#include "rsa-md4.h" +#include "arcfour-int.h" + +#if TARGET_OS_MAC && !defined(DEPEND) +#include +#endif + +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) +{ + krb5_error_code err = 0; + krb5_MD4_CTX md4_context; + unsigned char *copystr; + size_t copystrlen; + + 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. + */ + + err = krb5int_utf8cs_to_ucs2les(string->data, string->length, ©str, ©strlen); + if (err) + return err; + + /* the actual MD4 hash of the data */ + krb5_MD4Init(&md4_context); + krb5_MD4Update(&md4_context, copystr, copystrlen); + 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, copystrlen); + memset(&md4_context, 0, sizeof(md4_context)); + free(copystr); + return err; +} diff --git a/krb5-1-7/src/lib/crypto/arcfour/deps b/krb5-1-7/src/lib/crypto/arcfour/deps new file mode 100644 index 000000000..ee6faef82 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/arcfour/deps @@ -0,0 +1,37 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 arcfour-int.h \ + arcfour.c arcfour.h +arcfour_aead.so arcfour_aead.po $(OUTPRE)arcfour_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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)/../aead.h \ + $(srcdir)/../cksumtypes.h arcfour-int.h arcfour.h arcfour_aead.c +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-utf8.h $(SRCTOP)/include/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-7/src/lib/crypto/block_size.c b/krb5-1-7/src/lib/crypto/block_size.c new file mode 100644 index 000000000..e4c11e869 --- /dev/null +++ b/krb5-1-7/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; iblock_size; + + return(0); +} diff --git a/krb5-1-7/src/lib/crypto/cf2.c b/krb5-1-7/src/lib/crypto/cf2.c new file mode 100644 index 000000000..4e25641e8 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/cf2.c @@ -0,0 +1,154 @@ +/* + * lib/crypto/cf2.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * + * Implement KRB_FX_CF2 function per + *draft-ietf-krb-wg-preauth-framework-09. Take two keys and two + *pepper strings as input and return a combined key. + */ + +#include +#include +#include "etypes.h" + + +/* + * Call the PRF function multiple times with the pepper prefixed with + * a count byte to get enough bits of output. + */ +static krb5_error_code +prf_plus( krb5_context context, krb5_keyblock *k,const char *pepper, + size_t keybytes, char **out) +{ + krb5_error_code retval = 0; + size_t prflen, iterations; + krb5_data out_data; + krb5_data in_data; + char *buffer = NULL; + struct k5buf prf_inbuf; + krb5int_buf_init_dynamic(&prf_inbuf); + krb5int_buf_add_len( &prf_inbuf, "\001", 1); + krb5int_buf_add( &prf_inbuf, pepper); + retval = krb5_c_prf_length( context, k->enctype, &prflen); + if (retval != 0) + goto cleanup; + iterations = keybytes/prflen; + if ((keybytes%prflen) != 0) + iterations++; + assert(iterations <= 254); + buffer = malloc(iterations*prflen); + if (buffer == NULL) { + retval = ENOMEM; + goto cleanup; + } + if (krb5int_buf_len( &prf_inbuf) == -1) { + retval = ENOMEM; + goto cleanup; + } + in_data.length = (krb5_int32) krb5int_buf_len( &prf_inbuf); + in_data.data = krb5int_buf_data( &prf_inbuf); + out_data.length = prflen; + out_data.data = buffer; + + while (iterations > 0) { + retval = krb5_c_prf( context, k, &in_data, &out_data); + if (retval != 0) + goto cleanup; + out_data.data += prflen; + in_data.data[0]++; + iterations--; + } + cleanup: + if (retval == 0 ) + *out = buffer; + else{ + if (buffer != NULL) + free(buffer); + } + krb5int_free_buf( &prf_inbuf); + return retval; +} + + +krb5_error_code KRB5_CALLCONV +krb5_c_fx_cf2_simple(krb5_context context, + krb5_keyblock *k1, const char *pepper1, + krb5_keyblock *k2, const char *pepper2, + krb5_keyblock **out) +{ + const struct krb5_keytypes *out_enctype; + size_t keybytes, keylength, i; + char *prf1 = NULL, *prf2 = NULL; + krb5_data keydata; + krb5_enctype out_enctype_num; + krb5_error_code retval = 0; + krb5_keyblock *out_key = NULL; + + + if (k1 == NULL ||!krb5_c_valid_enctype(k1->enctype)) + return KRB5_BAD_ENCTYPE; + if (k2 == NULL || !krb5_c_valid_enctype(k2->enctype)) + return KRB5_BAD_ENCTYPE; + out_enctype_num = k1->enctype; + assert(out != NULL); + assert ((out_enctype = find_enctype(out_enctype_num)) != NULL); + if (out_enctype->prf == NULL) { + if (context) + krb5int_set_error(&(context->err) , KRB5_CRYPTO_INTERNAL, + "Enctype %d has no PRF", out_enctype_num); + return KRB5_CRYPTO_INTERNAL; + } + keybytes = out_enctype->enc->keybytes; + keylength = out_enctype->enc->keylength; + + retval = prf_plus( context, k1, pepper1, keybytes, &prf1); + if (retval != 0) + goto cleanup; + retval = prf_plus( context, k2, pepper2, keybytes, &prf2); + if (retval != 0) + goto cleanup; + for (i = 0; i < keybytes; i++) + prf1[i] ^= prf2[i]; + zap(prf2, keybytes); + retval = krb5int_c_init_keyblock( context, out_enctype_num, keylength, &out_key); + if (retval != 0) + goto cleanup; + keydata.data = prf1; + keydata.length = keybytes; + retval = out_enctype->enc->make_key( &keydata, out_key); + + cleanup: + if (retval == 0) + *out = out_key; + else krb5int_c_free_keyblock( context, out_key); + if (prf1 != NULL) { + zap(prf1, keybytes); + free(prf1); + } + if (prf2 != NULL) + free(prf2); + return retval; +} diff --git a/krb5-1-7/src/lib/crypto/checksum_length.c b/krb5-1-7/src/lib/crypto/checksum_length.c new file mode 100644 index 000000000..28846a671 --- /dev/null +++ b/krb5-1-7/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) +{ + unsigned int i; + + for (i=0; ihashsize; + 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-7/src/lib/crypto/cksumtype_to_string.c b/krb5-1-7/src/lib/crypto/cksumtype_to_string.c new file mode 100644 index 000000000..ee1d50ba5 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/cksumtype_to_string.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "cksumtypes.h" + +krb5_error_code KRB5_CALLCONV +krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen) +{ + unsigned int i; + + for (i=0; i= buflen) + return(ENOMEM); + return(0); + } + } + + return(EINVAL); +} diff --git a/krb5-1-7/src/lib/crypto/cksumtypes.c b/krb5-1-7/src/lib/crypto/cksumtypes.c new file mode 100644 index 000000000..037e53f49 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/cksumtypes.c @@ -0,0 +1,91 @@ +/* + * 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", { 0 }, "CRC-32", + 0, NULL, + &krb5int_hash_crc32 }, + + { CKSUMTYPE_RSA_MD4, 0, + "md4", { 0 }, "RSA-MD4", + 0, NULL, + &krb5int_hash_md4 }, + { CKSUMTYPE_RSA_MD4_DES, 0, + "md4-des", { 0 }, "RSA-MD4 with DES cbc mode", + ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md4des, + NULL }, + + { CKSUMTYPE_DESCBC, 0, + "des-cbc", { 0 }, "DES cbc mode", + ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_descbc, + NULL }, + + { CKSUMTYPE_RSA_MD5, 0, + "md5", { 0 }, "RSA-MD5", + 0, NULL, + &krb5int_hash_md5 }, + { CKSUMTYPE_RSA_MD5_DES, 0, + "md5-des", { 0 }, "RSA-MD5 with DES cbc mode", + ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md5des, + NULL }, + + { CKSUMTYPE_NIST_SHA, 0, + "sha", { 0 }, "NIST-SHA", + 0, NULL, + &krb5int_hash_sha1 }, + + { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE, + "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key", + 0, NULL, + &krb5int_hash_sha1 }, + { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5 (RC4 key)", + ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, + NULL }, + + { CKSUMTYPE_HMAC_SHA1_96_AES128, KRB5_CKSUMFLAG_DERIVE, + "hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key", + 0, NULL, + &krb5int_hash_sha1, 12 }, + { CKSUMTYPE_HMAC_SHA1_96_AES256, KRB5_CKSUMFLAG_DERIVE, + "hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key", + 0, NULL, + &krb5int_hash_sha1, 12 }, + { CKSUMTYPE_MD5_HMAC_ARCFOUR, 0, + "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC (RC4 key)", + ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_md5_hmac, + NULL } +}; + +const unsigned int krb5_cksumtypes_length = +sizeof(krb5_cksumtypes_list)/sizeof(struct krb5_cksumtypes); diff --git a/krb5-1-7/src/lib/crypto/cksumtypes.h b/krb5-1-7/src/lib/crypto/cksumtypes.h new file mode 100644 index 000000000..c667e8abe --- /dev/null +++ b/krb5-1-7/src/lib/crypto/cksumtypes.h @@ -0,0 +1,62 @@ +/* + * 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 CKSUMTYPES_H +#define CKSUMTYPES_H +#include "k5-int.h" + +struct krb5_cksumtypes { + krb5_cksumtype ctype; + unsigned int flags; + char *name; + char *aliases[2]; + 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 + +extern const struct krb5_cksumtypes krb5_cksumtypes_list[]; +extern const unsigned int krb5_cksumtypes_length; +#endif diff --git a/krb5-1-7/src/lib/crypto/coll_proof_cksum.c b/krb5-1-7/src/lib/crypto/coll_proof_cksum.c new file mode 100644 index 000000000..85fb57b9b --- /dev/null +++ b/krb5-1-7/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) +{ + unsigned int i; + + for (i=0; ienctype)&&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-7/src/lib/crypto/crc32/CRC.pm b/krb5-1-7/src/lib/crypto/crc32/CRC.pm new file mode 100644 index 000000000..ee2ab2ae8 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/crc32/Makefile.in b/krb5-1-7/src/lib/crypto/crc32/Makefile.in new file mode 100644 index 000000000..11df8607c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/crc32/Makefile.in @@ -0,0 +1,41 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/crc32/Poly.pm b/krb5-1-7/src/lib/crypto/crc32/Poly.pm new file mode 100644 index 000000000..cad0f77b5 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/crc32/crc-32.h b/krb5-1-7/src/lib/crypto/crc32/crc-32.h new file mode 100644 index 000000000..0efc00625 --- /dev/null +++ b/krb5-1-7/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 (krb5_pointer in, size_t in_length, unsigned long *c); + +#ifdef CRC32_SHIFT4 +void mit_crc32_shift4(krb5_pointer /* in */, + size_t /* in_length */, + unsigned long * /* cksum */); +#endif + +#endif /* KRB5_CRC32__ */ diff --git a/krb5-1-7/src/lib/crypto/crc32/crc.pl b/krb5-1-7/src/lib/crypto/crc32/crc.pl new file mode 100644 index 000000000..b21b6b15d --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/crc32/crc32.c b/krb5-1-7/src/lib/crypto/crc32/crc32.c new file mode 100644 index 000000000..ef65476d9 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/crc32/deps b/krb5-1-7/src/lib/crypto/crc32/deps new file mode 100644 index 000000000..9dc702d6e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/crc32/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/crc32/t_crc.c b/krb5-1-7/src/lib/crypto/crc32/t_crc.c new file mode 100644 index 000000000..e8a353a0b --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#include +#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-7/src/lib/crypto/crypto_length.c b/krb5-1-7/src/lib/crypto/crypto_length.c new file mode 100644 index 000000000..d99d18b27 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/crypto_length.c @@ -0,0 +1,170 @@ +/* + * lib/crypto/crypto_length.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#include "aead.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length(krb5_context context, + krb5_enctype enctype, + krb5_cryptotype type, + unsigned int *size) +{ + int i; + const struct krb5_keytypes *ktp = NULL; + krb5_error_code ret; + + for (i = 0; i < krb5_enctypes_length; i++) { + if (krb5_enctypes_list[i].etype == enctype) { + ktp = &krb5_enctypes_list[i]; + break; + } + } + + if (ktp == NULL || ktp->aead == NULL) { + return KRB5_BAD_ENCTYPE; + } + + switch (type) { + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + *size = 0; + ret = 0; + break; + case KRB5_CRYPTO_TYPE_DATA: + *size = (size_t)~0; /* match Heimdal */ + ret = 0; + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_PADDING: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + ret = ktp->aead->crypto_length(ktp->aead, ktp->enc, ktp->hash, type, size); + break; + default: + ret = EINVAL; + break; + } + + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_padding_length(krb5_context context, + krb5_enctype enctype, + size_t data_length, + unsigned int *pad_length) +{ + int i; + const struct krb5_keytypes *ktp = NULL; + + for (i = 0; i < krb5_enctypes_length; i++) { + if (krb5_enctypes_list[i].etype == enctype) { + ktp = &krb5_enctypes_list[i]; + break; + } + } + + if (ktp == NULL || ktp->aead == NULL) { + return KRB5_BAD_ENCTYPE; + } + + return krb5int_c_padding_length(ktp->aead, ktp->enc, ktp->hash, data_length, pad_length); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length_iov(krb5_context context, + krb5_enctype enctype, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret = 0; + size_t i; + const struct krb5_keytypes *ktp = NULL; + unsigned int data_length = 0, pad_length; + krb5_crypto_iov *padding = NULL; + + /* + * XXX need to rejig internal interface so we can accurately + * report variable header lengths + */ + + for (i = 0; i < (size_t)krb5_enctypes_length; i++) { + if (krb5_enctypes_list[i].etype == enctype) { + ktp = &krb5_enctypes_list[i]; + break; + } + } + + if (ktp == NULL || ktp->aead == NULL) { + return KRB5_BAD_ENCTYPE; + } + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + switch (iov->flags) { + case KRB5_CRYPTO_TYPE_DATA: + data_length += iov->data.length; + break; + case KRB5_CRYPTO_TYPE_PADDING: + if (padding != NULL) + return EINVAL; + + padding = iov; + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + ret = ktp->aead->crypto_length(ktp->aead, ktp->enc, ktp->hash, iov->flags, &iov->data.length); + break; + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + default: + break; + } + + if (ret != 0) + break; + } + + if (ret != 0) + return ret; + + ret = krb5int_c_padding_length(ktp->aead, ktp->enc, ktp->hash, data_length, &pad_length); + if (ret != 0) + return ret; + + if (pad_length != 0 && padding == NULL) + return EINVAL; + + if (padding != NULL) + padding->data.length = pad_length; + + return 0; +} + diff --git a/krb5-1-7/src/lib/crypto/crypto_libinit.c b/krb5-1-7/src/lib/crypto/crypto_libinit.c new file mode 100644 index 000000000..91bf8ac22 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/crypto_libinit.c @@ -0,0 +1,33 @@ +#include +#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-7/src/lib/crypto/decrypt.c b/krb5-1-7/src/lib/crypto/decrypt.c new file mode 100644 index 000000000..74c38f6aa --- /dev/null +++ b/krb5-1-7/src/lib/crypto/decrypt.c @@ -0,0 +1,67 @@ +/* + * 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 "aead.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; ienctype) + break; + } + + if (i == krb5_enctypes_length) { + krb5int_set_error(&context->err, KRB5_BAD_ENCTYPE, + "Bad encryption type (type %d unknown)", + key->enctype); + return(KRB5_BAD_ENCTYPE); + } + + if ((input->enctype != ENCTYPE_UNKNOWN) && + (krb5_enctypes_list[i].etype != input->enctype)) + return(KRB5_BAD_ENCTYPE); + + if (krb5_enctypes_list[i].decrypt == NULL) { + assert(krb5_enctypes_list[i].aead != NULL); + + return krb5int_c_decrypt_aead_compat(krb5_enctypes_list[i].aead, + krb5_enctypes_list[i].enc, + krb5_enctypes_list[i].hash, + key, usage, ivec, + &input->ciphertext, output); + } + + 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-7/src/lib/crypto/decrypt_iov.c b/krb5-1-7/src/lib/crypto/decrypt_iov.c new file mode 100644 index 000000000..1a98b0657 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/decrypt_iov.c @@ -0,0 +1,61 @@ +/* + * lib/crypto/encrypt_iov.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#include "aead.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt_iov(krb5_context context, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data) +{ + int i; + const struct krb5_keytypes *ktp = NULL; + + for (i = 0; i < krb5_enctypes_length; i++) { + if (krb5_enctypes_list[i].etype == key->enctype) { + ktp = &krb5_enctypes_list[i]; + break; + } + } + + if (ktp == NULL || ktp->aead == NULL) { + return KRB5_BAD_ENCTYPE; + } + + if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) { + return krb5int_c_iov_decrypt_stream(ktp->aead, ktp->enc, ktp->hash, + key, usage, cipher_state, data, num_data); + } + + return ktp->aead->decrypt_iov(ktp->aead, ktp->enc, ktp->hash, + key, usage, cipher_state, data, num_data); +} + diff --git a/krb5-1-7/src/lib/crypto/default_state.c b/krb5-1-7/src/lib/crypto/default_state.c new file mode 100644 index 000000000..33a189f26 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/deps b/krb5-1-7/src/lib/crypto/deps new file mode 100644 index 000000000..2d5b4a332 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/deps @@ -0,0 +1,535 @@ +# +# Generated makefile dependencies follow. +# +aead.so aead.po $(OUTPRE)aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 aead.c aead.h cksumtypes.h etypes.h +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_length.so crypto_length.po $(OUTPRE)crypto_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h aead.h cksumtypes.h \ + crypto_length.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + aead.h cksumtypes.h decrypt.c etypes.h +decrypt_iov.so decrypt_iov.po $(OUTPRE)decrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h aead.h cksumtypes.h \ + decrypt_iov.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + aead.h cksumtypes.h encrypt.c etypes.h +encrypt_iov.so encrypt_iov.po $(OUTPRE)encrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_iov.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h aead.h cksumtypes.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/des/des_int.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + aead.h cksumtypes.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_checksum_iov.so make_checksum_iov.po $(OUTPRE)make_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h aead.h cksumtypes.h \ + make_checksum_iov.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 +cf2.so cf2.po $(OUTPRE)cf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + cf2.c etypes.h +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +verify_checksum_iov.so verify_checksum_iov.po $(OUTPRE)verify_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h aead.h cksumtypes.h \ + verify_checksum_iov.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_cf2.so t_cf2.po $(OUTPRE)t_cf2.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h t_cf2.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_short.so t_short.po $(OUTPRE)t_short.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_short.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/des/ISSUES b/krb5-1-7/src/lib/crypto/des/ISSUES new file mode 100644 index 000000000..412f94aa7 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/des/Makefile.in b/krb5-1-7/src/lib/crypto/des/Makefile.in new file mode 100644 index 000000000..ef700a74d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/Makefile.in @@ -0,0 +1,104 @@ +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_aead.o \ + d3_kysched.o \ + des_prf.o \ + f_aead.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_aead.$(OBJEXT) \ + $(OUTPRE)d3_kysched.$(OBJEXT) \ + $(OUTPRE)des_prf.$(OBJEXT) \ + $(OUTPRE)f_aead.$(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_aead.c \ + $(srcdir)/d3_kysched.c \ + $(srcdir)/des_prf.c \ + $(srcdir)/f_aead.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@ + diff --git a/krb5-1-7/src/lib/crypto/des/afsstring2key.c b/krb5-1-7/src/lib/crypto/des/afsstring2key.c new file mode 100644 index 000000000..571dab007 --- /dev/null +++ b/krb5-1-7/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 + +#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; ilength; 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); + free(password); + } +#if 0 + /* must free here because it was copied for this special case */ + free(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>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-7/src/lib/crypto/des/d3_aead.c b/krb5-1-7/src/lib/crypto/des/d3_aead.c new file mode 100644 index 000000000..42ac395f3 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/d3_aead.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * 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" +#include "../aead.h" + +void +krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + for (;;) { + unsigned DES_INT32 temp; + + ip = iblock; + op = oblock; + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + + /* + * 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); + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) + memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); +} + +void +krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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 (num_data == 0) + return; + + /* + * Prime the old cipher with ivec. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + for (;;) { + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + ip = iblock; + op = oblock; + + 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; + + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) { + op = ivec; + PUT_HALF_BLOCK(ocipherl,op); + PUT_HALF_BLOCK(ocipherr, op); + } +} diff --git a/krb5-1-7/src/lib/crypto/des/d3_cbc.c b/krb5-1-7/src/lib/crypto/des/d3_cbc.c new file mode 100644 index 000000000..077e78d2c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/d3_cbc.c @@ -0,0 +1,223 @@ +/* + * 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) { + 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; + + } + 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-7/src/lib/crypto/des/d3_kysched.c b/krb5-1-7/src/lib/crypto/des/d3_kysched.c new file mode 100644 index 000000000..f18cc2419 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/des/deps b/krb5-1-7/src/lib/crypto/des/deps new file mode 100644 index 000000000..93147df27 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/deps @@ -0,0 +1,146 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_aead.so d3_aead.po $(OUTPRE)d3_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../cksumtypes.h d3_aead.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +des_prf.so des_prf.po $(OUTPRE)des_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 des_prf.c +f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../cksumtypes.h des_int.h \ + f_aead.c f_tables.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-7/src/lib/crypto/des/des_int.h b/krb5-1-7/src/lib/crypto/des/des_int.h new file mode 100644 index 000000000..4a1d52ae3 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/des_int.h @@ -0,0 +1,382 @@ +/* + * 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__ + +#if defined(__MACH__) && defined(__APPLE__) +#include +#include +#if TARGET_RT_MAC_CFM +#error "Use KfM 4.0 SDK headers for CFM compilation." +#endif +#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS) +#define KRB5INT_DES_DEPRECATED 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 + +#include + +#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; + +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); + +void +krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + 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) + +void +krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +/* 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); +krb5_error_code +krb5int_des_prf (const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); +#endif /*DES_INTERNAL_DEFS*/ diff --git a/krb5-1-7/src/lib/crypto/des/des_prf.c b/krb5-1-7/src/lib/crypto/des/des_prf.c new file mode 100644 index 000000000..9bb1085c3 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/des_prf.c @@ -0,0 +1,54 @@ +/* + * lib/crypto/des/des_prf.c + * + * Copyright (C) 2004, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + * des-cbc-crc, des-cbc-md4, and des-cbc-md5 enctypes. + */ + +#include "k5-int.h" +#include "../hash_provider/hash_provider.h" /* XXX is this ok? */ + +krb5_error_code +krb5int_des_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_error_code ret = 0; + + hash = &krb5int_hash_md5; /* MD5 is always used. */ + tmp.length = hash->hashsize; + tmp.data = malloc(hash->hashsize); + if (tmp.data == NULL) + return ENOMEM; + ret = hash->hash(1, in, &tmp); + if (ret == 0) + ret = enc->encrypt(key, NULL, &tmp, out); + free(tmp.data); + return ret; +} diff --git a/krb5-1-7/src/lib/crypto/des/destest.c b/krb5-1-7/src/lib/crypto/des/destest.c new file mode 100644 index 000000000..2582cc3d3 --- /dev/null +++ b/krb5-1-7/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 + +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)&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 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-7/src/lib/crypto/des/f_aead.c b/krb5-1-7/src/lib/crypto/des/f_aead.c new file mode 100644 index 000000000..3366c67ef --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/f_aead.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * 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" +#include "../aead.h" + +void +krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + for (;;) { + unsigned DES_INT32 temp; + + ip = iblock; + op = oblock; + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) + memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); +} + +void +krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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 (num_data == 0) + return; + + /* + * Prime the old cipher with ivec. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + for (;;) { + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + ip = iblock; + op = oblock; + + 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; + + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) { + op = ivec; + PUT_HALF_BLOCK(ocipherl, op); + PUT_HALF_BLOCK(ocipherr, op); + } +} diff --git a/krb5-1-7/src/lib/crypto/des/f_cbc.c b/krb5-1-7/src/lib/crypto/des/f_cbc.c new file mode 100644 index 000000000..0949ba140 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/f_cbc.c @@ -0,0 +1,274 @@ +/* + * lib/crypto/des/f_cbc.c + * + * Copyright (C) 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. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * 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 */ + } + } +} + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +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-7/src/lib/crypto/des/f_cksum.c b/krb5-1-7/src/lib/crypto/des/f_cksum.c new file mode 100644 index 000000000..1c03da43e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/f_cksum.c @@ -0,0 +1,136 @@ +/* + * lib/crypto/des/f_cksum.c + * + * Copyright (C) 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. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * 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) { + unsigned DES_INT32 temp; + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + 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-7/src/lib/crypto/des/f_parity.c b/krb5-1-7/src/lib/crypto/des/f_parity.c new file mode 100644 index 000000000..426386303 --- /dev/null +++ b/krb5-1-7/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)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +void +mit_des_fixup_key_parity(mit_des_cblock key) +{ + unsigned int i; + for (i=0; i> 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 = load_32_be(k), k += 4; + + 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-7/src/lib/crypto/des/f_tables.c b/krb5-1-7/src/lib/crypto/des/f_tables.c new file mode 100644 index 000000000..42426bc0a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/f_tables.c @@ -0,0 +1,370 @@ +/* + * lib/crypto/des/f_tables.c + * + * Copyright (C) 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. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * 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-7/src/lib/crypto/des/f_tables.h b/krb5-1-7/src/lib/crypto/des/f_tables.h new file mode 100644 index 000000000..45a6322fe --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/f_tables.h @@ -0,0 +1,279 @@ +/* + * lib/crypto/des/f_tables.h + * + * Copyright (C) 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. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * 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) + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +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-7/src/lib/crypto/des/key_sched.c b/krb5-1-7/src/lib/crypto/des/key_sched.c new file mode 100644 index 000000000..26449a94c --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/des/keytest.data b/krb5-1-7/src/lib/crypto/des/keytest.data new file mode 100644 index 000000000..7ff34eedc --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/des/string2key.c b/krb5-1-7/src/lib/crypto/des/string2key.c new file mode 100644 index 000000000..0ce413685 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/des/string2key.c @@ -0,0 +1,261 @@ +/* + * lib/crypto/des/des_s2k.c + * + * Copyright 2004, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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; + unsigned 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 ENOMEM; + 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-7/src/lib/crypto/des/t_afss2k.c b/krb5-1-7/src/lib/crypto/des/t_afss2k.c new file mode 100644 index 000000000..a6d0aa58d --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/des/t_verify.c b/krb5-1-7/src/lib/crypto/des/t_verify.c new file mode 100644 index 000000000..a6ad07cb8 --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/crypto/des/weak_key.c b/krb5-1-7/src/lib/crypto/des/weak_key.c new file mode 100644 index 000000000..2eab9f543 --- /dev/null +++ b/krb5-1-7/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) +{ + unsigned 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-7/src/lib/crypto/dk/Makefile.in b/krb5-1-7/src/lib/crypto/dk/Makefile.in new file mode 100644 index 000000000..c15978e40 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/Makefile.in @@ -0,0 +1,55 @@ +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_aead.o \ + dk_decrypt.o \ + dk_encrypt.o \ + derive.o \ + dk_prf.o \ + stringtokey.o + +OBJS=\ + $(OUTPRE)checksum.$(OBJEXT) \ + $(OUTPRE)dk_aead.$(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_aead.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@ + diff --git a/krb5-1-7/src/lib/crypto/dk/checksum.c b/krb5-1-7/src/lib/crypto/dk/checksum.c new file mode 100644 index 000000000..f4b18bf0c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/checksum.c @@ -0,0 +1,168 @@ +/* + * 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" +#include "aead.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; ienctype) + 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; + + store_32_be(usage, constantdata); + + 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); +} + +krb5_error_code +krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + 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; ienctype) + 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; + + store_32_be(usage, constantdata); + + datain.data[4] = (char) 0x99; + + if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0) + goto cleanup; + + /* hash the data */ + + if ((ret = krb5int_hmac_iov(hash, &kc, data, num_data, 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-7/src/lib/crypto/dk/deps b/krb5-1-7/src/lib/crypto/dk/deps new file mode 100644 index 000000000..e901a5483 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/deps @@ -0,0 +1,76 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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)/../aead.h \ + $(srcdir)/../cksumtypes.h $(srcdir)/../etypes.h checksum.c \ + dk.h +dk_aead.so dk_aead.po $(OUTPRE)dk_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../cksumtypes.h dk.h \ + dk_aead.c +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-7/src/lib/crypto/dk/derive.c b/krb5-1-7/src/lib/crypto/dk/derive.c new file mode 100644 index 000000000..77b05fa1a --- /dev/null +++ b/krb5-1-7/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 = (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(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 = (char *) 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 = (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(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; imake_key (inblock, outkey); +} +#endif diff --git a/krb5-1-7/src/lib/crypto/dk/dk.h b/krb5-1-7/src/lib/crypto/dk/dk.h new file mode 100644 index 000000000..bc40134ef --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/dk.h @@ -0,0 +1,124 @@ +/* + * 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 +krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + 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); + +/* AEAD */ + +extern const struct krb5_aead_provider krb5int_aead_dk; +extern const struct krb5_aead_provider krb5int_aead_aes; + +/* CCM */ + +void +krb5int_ccm_encrypt_length(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length); + +extern const struct krb5_aead_provider krb5int_aead_ccm; + +krb5_error_code krb5int_ccm_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 *arg_output); + +krb5_error_code krb5int_ccm_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-7/src/lib/crypto/dk/dk_aead.c b/krb5-1-7/src/lib/crypto/dk/dk_aead.c new file mode 100644 index 000000000..f2f98b670 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/dk_aead.c @@ -0,0 +1,381 @@ +/* + * lib/crypto/dk/dk_aead.c + * + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "dk.h" +#include "aead.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +/* AEAD */ + +static krb5_error_code +krb5int_dk_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_PADDING: + *length = enc->block_size; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = hash->hashsize; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length"); + break; + } + + return 0; +} + +static krb5_error_code +krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data d1, d2; + krb5_crypto_iov *header, *trailer, *padding; + krb5_keyblock ke, ki; + size_t i; + unsigned int blocksize = 0; + unsigned int plainlen = 0; + unsigned int hmacsize = 0; + unsigned int padsize = 0; + unsigned char *cksum = NULL; + + ke.contents = ki.contents = NULL; + ke.length = ki.length = 0; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &hmacsize); + if (ret != 0) + return ret; + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + /* Validate header and trailer lengths. */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < hmacsize) + return KRB5_BAD_MSIZE; + + if (blocksize != 0) { + /* Check that the input data is correctly padded */ + if (plainlen % blocksize) + padsize = blocksize - (plainlen % blocksize); + } + + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padsize && (padding == NULL || padding->data.length < padsize)) + return KRB5_BAD_MSIZE; + + if (padding != NULL) { + memset(padding->data.data, 0, padsize); + padding->data.length = padsize; + } + + ke.length = enc->keylength; + ke.contents = malloc(ke.length); + if (ke.contents == NULL) { + ret = ENOMEM; + goto cleanup; + } + ki.length = enc->keylength; + ki.contents = malloc(ki.length); + if (ki.contents == NULL) { + ret = ENOMEM; + goto cleanup; + } + cksum = (unsigned char *)malloc(hash->hashsize); + if (cksum == NULL) { + ret = ENOMEM; + goto cleanup; + } + + /* derive the keys */ + + d1.data = (char *)constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + d1.data[4] = 0xAA; + + ret = krb5_derive_key(enc, key, &ke, &d1); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5_derive_key(enc, key, &ki, &d1); + if (ret != 0) + goto cleanup; + + /* generate confounder */ + + header->data.length = enc->block_size; + + ret = krb5_c_random_make_octets(/* XXX */ NULL, &header->data); + if (ret != 0) + goto cleanup; + + /* hash the plaintext */ + d2.length = hash->hashsize; + d2.data = (char *)cksum; + + ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d2); + if (ret != 0) + goto cleanup; + + /* encrypt the plaintext (header | data | padding) */ + assert(enc->encrypt_iov != NULL); + + ret = enc->encrypt_iov(&ke, ivec, data, num_data); /* will update ivec */ + if (ret != 0) + goto cleanup; + + /* possibly truncate the hash */ + assert(hmacsize <= d2.length); + + memcpy(trailer->data.data, cksum, hmacsize); + trailer->data.length = hmacsize; + +cleanup: + if (ke.contents != NULL) { + memset(ke.contents, 0, ke.length); + free(ke.contents); + } + if (ki.contents != NULL) { + memset(ki.contents, 0, ki.length); + free(ki.contents); + } + if (cksum != NULL) { + free(cksum); + } + + return ret; +} + +static krb5_error_code +krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data d1; + krb5_crypto_iov *header, *trailer; + krb5_keyblock ke, ki; + size_t i; + unsigned int blocksize = 0; /* careful, this is enc block size not confounder len */ + unsigned int cipherlen = 0; + unsigned int hmacsize = 0; + unsigned char *cksum = NULL; + + if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) { + return krb5int_c_iov_decrypt_stream(aead, enc, hash, key, + usage, ivec, data, num_data); + } + + ke.contents = ki.contents = NULL; + ke.length = ki.length = 0; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &hmacsize); + if (ret != 0) + return ret; + + if (blocksize != 0) { + /* Check that the input data is correctly padded. */ + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + cipherlen += iov->data.length; + } + if (cipherlen % blocksize != 0) + return KRB5_BAD_MSIZE; + } + + /* Validate header and trailer lengths */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != hmacsize) + return KRB5_BAD_MSIZE; + + ke.length = enc->keylength; + ke.contents = malloc(ke.length); + if (ke.contents == NULL) { + ret = ENOMEM; + goto cleanup; + } + ki.length = enc->keylength; + ki.contents = malloc(ki.length); + if (ki.contents == NULL) { + ret = ENOMEM; + goto cleanup; + } + cksum = (unsigned char *)malloc(hash->hashsize); + if (cksum == NULL) { + ret = ENOMEM; + goto cleanup; + } + + /* derive the keys */ + + d1.data = (char *)constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + d1.data[4] = 0xAA; + + ret = krb5_derive_key(enc, key, &ke, &d1); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5_derive_key(enc, key, &ki, &d1); + if (ret != 0) + goto cleanup; + + /* decrypt the plaintext (header | data | padding) */ + assert(enc->decrypt_iov != NULL); + + ret = enc->decrypt_iov(&ke, ivec, data, num_data); /* will update ivec */ + if (ret != 0) + goto cleanup; + + /* verify the hash */ + d1.length = hash->hashsize; /* non-truncated length */ + d1.data = (char *)cksum; + + ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + /* compare only the possibly truncated length */ + if (memcmp(cksum, trailer->data.data, hmacsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + if (ke.contents != NULL) { + memset(ke.contents, 0, ke.length); + free(ke.contents); + } + if (ki.contents != NULL) { + memset(ki.contents, 0, ki.length); + free(ki.contents); + } + if (cksum != NULL) { + free(cksum); + } + + return ret; +} + +const struct krb5_aead_provider krb5int_aead_dk = { + krb5int_dk_crypto_length, + krb5int_dk_encrypt_iov, + krb5int_dk_decrypt_iov +}; + +static krb5_error_code +krb5int_aes_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + *length = enc->block_size; + break; + case KRB5_CRYPTO_TYPE_PADDING: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = 96 / 8; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length"); + break; + } + + return 0; +} + +const struct krb5_aead_provider krb5int_aead_aes = { + krb5int_aes_crypto_length, + krb5int_dk_encrypt_iov, + krb5int_dk_decrypt_iov +}; + diff --git a/krb5-1-7/src/lib/crypto/dk/dk_decrypt.c b/krb5-1-7/src/lib/crypto/dk/dk_decrypt.c new file mode 100644 index 000000000..b23bd4828 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/dk_decrypt.c @@ -0,0 +1,206 @@ +/* + * 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; + + /* Verify input and output lengths. */ + if (input->length < blocksize + hmacsize) + return KRB5_BAD_MSIZE; + if (output->length < input->length - blocksize - hmacsize) + return KRB5_BAD_MSIZE; + + 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; + + store_32_be(usage, constantdata); + + 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-7/src/lib/crypto/dk/dk_encrypt.c b/krb5-1-7/src/lib/crypto/dk/dk_encrypt.c new file mode 100644 index 000000000..6596e53ce --- /dev/null +++ b/krb5-1-7/src/lib/crypto/dk/dk_encrypt.c @@ -0,0 +1,358 @@ +/* + * 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; + char *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 = (char *) constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + 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 = (char *) 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 = (char *) 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 ENOMEM; + 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; + char *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 = (char *) constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + 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 = (char *) 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 = (char *) 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-7/src/lib/crypto/dk/dk_prf.c b/krb5-1-7/src/lib/crypto/dk/dk_prf.c new file mode 100644 index 000000000..ec64caf16 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/dk/stringtokey.c b/krb5-1-7/src/lib/crypto/dk/stringtokey.c new file mode 100644 index 000000000..0e54b849f --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/enc_provider/Makefile.in b/krb5-1-7/src/lib/crypto/enc_provider/Makefile.in new file mode 100644 index 000000000..bb15ecf6e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/Makefile.in @@ -0,0 +1,42 @@ +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 -I$(srcdir)/.. +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@ + diff --git a/krb5-1-7/src/lib/crypto/enc_provider/aes.c b/krb5-1-7/src/lib/crypto/enc_provider/aes.c new file mode 100644 index 000000000..f14847252 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/aes.c @@ -0,0 +1,422 @@ +/* + * lib/crypto/enc_provider/aes.c + * + * Copyright (C) 2003, 2007, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "aes.h" +#include "../aead.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 + +static inline void enc(char *out, const char *in, aes_ctx *ctx) +{ + if (aes_enc_blk((const unsigned char *)in, (unsigned char *)out, ctx) + != aes_good) + abort(); +} +static inline void dec(char *out, const char *in, aes_ctx *ctx) +{ + if (aes_dec_blk((const unsigned char *)in, (unsigned char *)out, ctx) + != aes_good) + 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; + 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) { + /* Used when deriving keys. */ + if (input->length < BLOCK_SIZE) + return KRB5_BAD_MSIZE; + enc(output->data, input->data, &ctx); + } else if (nblocks > 1) { + 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; + 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) + return KRB5_BAD_MSIZE; + dec(output->data, input->data, &ctx); + } else if (nblocks > 1) { + + 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 +krb5int_aes_encrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + aes_ctx ctx; + char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE]; + int nblocks = 0, blockno; + size_t input_length, i; + struct iov_block_state input_pos, output_pos; + + if (aes_enc_key(key->contents, key->length, &ctx) != aes_good) + abort(); + + if (ivec != NULL) + memcpy(tmp, ivec->data, BLOCK_SIZE); + else + memset(tmp, 0, BLOCK_SIZE); + + for (i = 0, input_length = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + input_length += iov->data.length; + } + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + krb5int_c_iov_get_block((unsigned char *)tmp, BLOCK_SIZE, + data, num_data, &input_pos); + enc(tmp2, tmp, &ctx); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, + BLOCK_SIZE, &output_pos); + } else if (nblocks > 1) { + char blockN2[BLOCK_SIZE]; /* second last */ + char blockN1[BLOCK_SIZE]; /* last block */ + + for (blockno = 0; blockno < nblocks - 2; blockno++) { + char blockN[BLOCK_SIZE]; + + krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos); + xorblock(tmp, blockN); + enc(tmp2, tmp, &ctx); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos); + + /* 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). */ + + /* First, get the last two blocks */ + memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */ + krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos); + krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos); + + /* Encrypt second last block */ + xorblock(tmp, blockN2); + enc(tmp2, tmp, &ctx); + memcpy(blockN2, tmp2, BLOCK_SIZE); /* blockN2 now contains first block */ + memcpy(tmp, tmp2, BLOCK_SIZE); + + /* Encrypt last block */ + xorblock(tmp, blockN1); + enc(tmp2, tmp, &ctx); + memcpy(blockN1, tmp2, BLOCK_SIZE); + + /* Put the last two blocks back into the iovec (reverse order) */ + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos); + + if (ivec != NULL) + memcpy(ivec->data, blockN1, BLOCK_SIZE); + } + + return 0; +} + +static krb5_error_code +krb5int_aes_decrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + aes_ctx ctx; + char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE]; + int nblocks = 0, blockno, i; + size_t input_length; + struct iov_block_state input_pos, output_pos; + + CHECK_SIZES; + + if (aes_dec_key(key->contents, key->length, &ctx) != aes_good) + abort(); + + if (ivec != NULL) + memcpy(tmp, ivec->data, BLOCK_SIZE); + else + memset(tmp, 0, BLOCK_SIZE); + + for (i = 0, input_length = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + input_length += iov->data.length; + } + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + krb5int_c_iov_get_block((unsigned char *)tmp, BLOCK_SIZE, + data, num_data, &input_pos); + dec(tmp2, tmp, &ctx); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, + BLOCK_SIZE, &output_pos); + } else if (nblocks > 1) { + char blockN2[BLOCK_SIZE]; /* second last */ + char blockN1[BLOCK_SIZE]; /* last block */ + + for (blockno = 0; blockno < nblocks - 2; blockno++) { + char blockN[BLOCK_SIZE]; + + krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos); + dec(tmp2, blockN, &ctx); + xorblock(tmp2, tmp); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos); + memcpy(tmp, blockN, BLOCK_SIZE); + } + + /* Do last two blocks, the second of which (next-to-last block + of plaintext) may be incomplete. */ + + /* First, get the last two encrypted blocks */ + memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */ + krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos); + krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos); + + /* Decrypt second last block */ + dec(tmp2, blockN2, &ctx); + /* Set tmp2 to last (possibly partial) plaintext block, and + save it. */ + xorblock(tmp2, blockN1); + memcpy(blockN2, tmp2, BLOCK_SIZE); + + /* Maybe keep the trailing part, and copy in the last + ciphertext block. */ + input_length %= BLOCK_SIZE; + memcpy(tmp2, blockN1, input_length ? input_length : BLOCK_SIZE); + dec(tmp3, tmp2, &ctx); + xorblock(tmp3, tmp); + /* Copy out ivec first before we clobber blockN1 with plaintext */ + if (ivec != NULL) + memcpy(ivec->data, blockN1, BLOCK_SIZE); + memcpy(blockN1, tmp3, BLOCK_SIZE); + + /* Put the last two blocks back into the iovec */ + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos); + krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos); + } + + 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, + krb5int_aes_encrypt_iov, + krb5int_aes_decrypt_iov +}; + +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, + krb5int_aes_encrypt_iov, + krb5int_aes_decrypt_iov +}; + diff --git a/krb5-1-7/src/lib/crypto/enc_provider/deps b/krb5-1-7/src/lib/crypto/enc_provider/deps new file mode 100644 index 000000000..44c1e722b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/deps @@ -0,0 +1,48 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../cksumtypes.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../cksumtypes.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../aes/aes.h $(srcdir)/../aes/uitypes.h \ + $(srcdir)/../cksumtypes.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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)/../aead.h $(srcdir)/../arcfour/arcfour-int.h \ + $(srcdir)/../arcfour/arcfour.h $(srcdir)/../cksumtypes.h \ + enc_provider.h rc4.c diff --git a/krb5-1-7/src/lib/crypto/enc_provider/des.c b/krb5-1-7/src/lib/crypto/enc_provider/des.c new file mode 100644 index 000000000..63c43517e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/des.c @@ -0,0 +1,181 @@ +/* + * 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" +#include "aead.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 + ? (const unsigned char *) ivec->data + : (const 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); +} + +static krb5_error_code +k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data, int enc) +{ + mit_des_key_schedule schedule; + size_t input_length = 0; + int i; + + /* key->enctype was checked by the caller */ + + if (key->length != 8) + return(KRB5_BAD_KEYSIZE); + + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_DATA_IOV(iov)) + input_length += iov->data.length; + } + + if ((input_length % 8) != 0) + return(KRB5_BAD_MSIZE); + if (ivec && (ivec->length != 8)) + 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 */ + if (enc) + krb5int_des_cbc_encrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL); + else + krb5int_des_cbc_decrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL); + + memset(schedule, 0, sizeof(schedule)); + + return(0); +} + +static krb5_error_code +k5_des_encrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + return k5_des_docrypt_iov(key, ivec, data, num_data, 1); +} + +static krb5_error_code +k5_des_decrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + return k5_des_docrypt_iov(key, ivec, data, num_data, 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, + k5_des_encrypt_iov, + k5_des_decrypt_iov +}; diff --git a/krb5-1-7/src/lib/crypto/enc_provider/des3.c b/krb5-1-7/src/lib/crypto/enc_provider/des3.c new file mode 100644 index 000000000..e7a07f64c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/des3.c @@ -0,0 +1,221 @@ +/* + * 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 "../aead.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 +validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec, + const krb5_crypto_iov *data, size_t num_data, + mit_des3_key_schedule *schedule) +{ + size_t i, input_length; + + for (i = 0, input_length = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + input_length += iov->data.length; + } + + 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); + + 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?(const unsigned char *) ivec->data:(const 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?(const unsigned char *) ivec->data:(const 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); +} + +static krb5_error_code +k5_des3_encrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_encrypt_iov(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (const unsigned char *) ivec->data : NULL); + + zap(schedule, sizeof(schedule)); + + return(0); +} + +static krb5_error_code +k5_des3_decrypt_iov(const krb5_keyblock *key, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_decrypt_iov(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (const unsigned char *) ivec->data : NULL); + + zap(schedule, sizeof(schedule)); + + 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, + k5_des3_encrypt_iov, + k5_des3_decrypt_iov +}; + diff --git a/krb5-1-7/src/lib/crypto/enc_provider/enc_provider.h b/krb5-1-7/src/lib/crypto/enc_provider/enc_provider.h new file mode 100644 index 000000000..92022b3c8 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/enc_provider.h @@ -0,0 +1,36 @@ +/* + * 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; +extern const struct krb5_enc_provider krb5int_enc_aes128_ctr; +extern const struct krb5_enc_provider krb5int_enc_aes256_ctr; + diff --git a/krb5-1-7/src/lib/crypto/enc_provider/rc4.c b/krb5-1-7/src/lib/crypto/enc_provider/rc4.c new file mode 100644 index 000000000..b950a605b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/enc_provider/rc4.c @@ -0,0 +1,271 @@ +/* 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" +#include "../aead.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 struct { + size_t length; + const unsigned char *data; +} arcfour_weakkeys[] = { + { sizeof (arcfour_weakkey1), arcfour_weakkey1}, + { sizeof (arcfour_weakkey2), arcfour_weakkey2}, +}; + +static inline unsigned int k5_arcfour_byte(ArcfourContext * ctx) +{ + 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; + counter < sizeof(arcfour_weakkeys)/sizeof(arcfour_weakkeys[0]); + counter++) + if (!memcmp(key, arcfour_weakkeys[counter].data, + arcfour_weakkeys[counter].length)) + 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; +} + +/* In-place encryption */ +static krb5_error_code +k5_arcfour_docrypt_iov(const krb5_keyblock *key, + const krb5_data *state, + krb5_crypto_iov *data, + size_t num_data) +{ + ArcfourContext *arcfour_ctx = NULL; + ArcFourCipherState *cipher_state = NULL; + krb5_error_code ret; + size_t i; + + if (key->length != 16) + return KRB5_BAD_KEYSIZE; + if (state != NULL && (state->length != sizeof(ArcFourCipherState))) + return KRB5_BAD_MSIZE; + + if (state != NULL) { + cipher_state = (ArcFourCipherState *)state->data; + arcfour_ctx = &cipher_state->ctx; + if (cipher_state->initialized == 0) { + ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length); + if (ret != 0) + return ret; + + cipher_state->initialized = 1; + } + } else { + arcfour_ctx = (ArcfourContext *)malloc(sizeof(ArcfourContext)); + if (arcfour_ctx == NULL) + return ENOMEM; + + ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length); + if (ret != 0) { + free(arcfour_ctx); + return ret; + } + } + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + k5_arcfour_crypt(arcfour_ctx, (unsigned char *)iov->data.data, + (const unsigned char *)iov->data.data, iov->data.length); + } + + if (state == NULL) { + 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, + k5_arcfour_docrypt_iov, + k5_arcfour_docrypt_iov +}; + diff --git a/krb5-1-7/src/lib/crypto/encrypt.c b/krb5-1-7/src/lib/crypto/encrypt.c new file mode 100644 index 000000000..a9a38aa77 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/encrypt.c @@ -0,0 +1,63 @@ +/* + * 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 "aead.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; ienctype) + break; + } + + if (i == krb5_enctypes_length) + return(KRB5_BAD_ENCTYPE); + + output->magic = KV5M_ENC_DATA; + output->kvno = 0; + output->enctype = key->enctype; + + if (krb5_enctypes_list[i].encrypt == NULL) { + assert(krb5_enctypes_list[i].aead != NULL); + + return krb5int_c_encrypt_aead_compat(krb5_enctypes_list[i].aead, + krb5_enctypes_list[i].enc, + krb5_enctypes_list[i].hash, + key, usage, ivec, + input, &output->ciphertext); + } + + 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-7/src/lib/crypto/encrypt_iov.c b/krb5-1-7/src/lib/crypto/encrypt_iov.c new file mode 100644 index 000000000..a35c5b577 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/encrypt_iov.c @@ -0,0 +1,55 @@ +/* + * lib/crypto/encrypt_iov.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KRB5_CALLCONV +krb5_c_encrypt_iov(krb5_context context, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data) +{ + int i; + const struct krb5_keytypes *ktp = NULL; + + for (i = 0; i < krb5_enctypes_length; i++) { + if (krb5_enctypes_list[i].etype == key->enctype) { + ktp = &krb5_enctypes_list[i]; + break; + } + } + + if (ktp == NULL || ktp->aead == NULL) { + return KRB5_BAD_ENCTYPE; + } + + return ktp->aead->encrypt_iov(ktp->aead, ktp->enc, ktp->hash, + key, usage, cipher_state, data, num_data); +} + diff --git a/krb5-1-7/src/lib/crypto/encrypt_length.c b/krb5-1-7/src/lib/crypto/encrypt_length.c new file mode 100644 index 000000000..a934b2a21 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/encrypt_length.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 "etypes.h" +#include "aead.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= buflen) + return(ENOMEM); + return(0); + } + } + + return(EINVAL); +} diff --git a/krb5-1-7/src/lib/crypto/etypes.c b/krb5-1-7/src/lib/crypto/etypes.c new file mode 100644 index 000000000..c44ee413e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/etypes.c @@ -0,0 +1,169 @@ +/* + * 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" +#include "des/des_int.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", { 0 }, "DES cbc mode with CRC-32", + &krb5int_enc_des, &krb5int_hash_crc32, + 16, + krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, + krb5int_des_string_to_key, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5, + NULL, /*AEAD*/ + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_MD4, + "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", + &krb5int_enc_des, &krb5int_hash_md4, + 16, + krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, + krb5int_des_string_to_key, + krb5int_des_prf, + CKSUMTYPE_RSA_MD4, + NULL, /*AEAD*/ + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_MD5, + "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", + &krb5int_enc_des, &krb5int_hash_md5, + 16, + krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, + krb5int_des_string_to_key, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5, + NULL, /*AEAD*/ + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_RAW, + "des-cbc-raw", { 0 }, "DES cbc mode raw", + &krb5int_enc_des, NULL, + 16, + krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, + krb5int_des_string_to_key, + krb5int_des_prf, + 0, + &krb5int_aead_raw, + ETYPE_WEAK }, + { ENCTYPE_DES3_CBC_RAW, + "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", + &krb5int_enc_des3, NULL, + 16, + krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, + krb5int_dk_string_to_key, + NULL, /*PRF*/ + 0, + &krb5int_aead_raw, + ETYPE_WEAK }, + + { ENCTYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, + "Triple DES cbc mode with HMAC/sha1", + &krb5int_enc_des3, &krb5int_hash_sha1, + 16, + krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, + krb5int_dk_string_to_key, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_DES3, + &krb5int_aead_dk, + 0 /*flags*/ }, + + { ENCTYPE_DES_HMAC_SHA1, + "des-hmac-sha1", { 0 }, "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, + NULL, + ETYPE_WEAK }, + { ENCTYPE_ARCFOUR_HMAC, + "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, + "ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, + krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, + krb5int_arcfour_prf, /*PRF*/ + CKSUMTYPE_HMAC_MD5_ARCFOUR, + &krb5int_aead_arcfour, + 0 /*flags*/ }, + { ENCTYPE_ARCFOUR_HMAC_EXP, + "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, + "Exportable ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, + krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, + krb5int_arcfour_prf, /*PRF*/ + CKSUMTYPE_HMAC_MD5_ARCFOUR, + &krb5int_aead_arcfour, + ETYPE_WEAK + }, + + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "aes128-cts-hmac-sha1-96", { "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, + &krb5int_aead_aes, + 0 /*flags*/ }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "aes256-cts-hmac-sha1-96", { "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, + &krb5int_aead_aes, + 0 /*flags*/ }, +}; + +const int krb5_enctypes_length = +sizeof(krb5_enctypes_list)/sizeof(struct krb5_keytypes); diff --git a/krb5-1-7/src/lib/crypto/etypes.h b/krb5-1-7/src/lib/crypto/etypes.h new file mode 100644 index 000000000..8441fcabc --- /dev/null +++ b/krb5-1-7/src/lib/crypto/etypes.h @@ -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" + +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 *name; + char *aliases[2]; + 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; + const struct krb5_aead_provider *aead; + krb5_flags flags; +}; + +#define ETYPE_WEAK 1 + +extern const struct krb5_keytypes krb5_enctypes_list[]; +extern const int krb5_enctypes_length; + +static inline const struct krb5_keytypes* +find_enctype (krb5_enctype enctype) +{ + int i; + for (i=0; ilength != CRC32_CKSUM_LENGTH) + return(KRB5_CRYPTO_INTERNAL); + + c = 0; + for (i=0; idata); + return(0); +} + +const struct krb5_hash_provider krb5int_hash_crc32 = { + CRC32_CKSUM_LENGTH, + 1, + k5_crc32_hash +}; diff --git a/krb5-1-7/src/lib/crypto/hash_provider/hash_md4.c b/krb5-1-7/src/lib/crypto/hash_provider/hash_md4.c new file mode 100644 index 000000000..1fa23c214 --- /dev/null +++ b/krb5-1-7/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; + unsigned int i; + + if (output->length != RSA_MD4_CKSUM_LENGTH) + return(KRB5_CRYPTO_INTERNAL); + + krb5_MD4Init(&ctx); + for (i=0; idata, 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-7/src/lib/crypto/hash_provider/hash_md5.c b/krb5-1-7/src/lib/crypto/hash_provider/hash_md5.c new file mode 100644 index 000000000..174c432a4 --- /dev/null +++ b/krb5-1-7/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; + unsigned int i; + + if (output->length != RSA_MD5_CKSUM_LENGTH) + return(KRB5_CRYPTO_INTERNAL); + + krb5_MD5Init(&ctx); + for (i=0; idata, 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-7/src/lib/crypto/hash_provider/hash_provider.h b/krb5-1-7/src/lib/crypto/hash_provider/hash_provider.h new file mode 100644 index 000000000..4fa46097d --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/hash_provider/hash_sha1.c b/krb5-1-7/src/lib/crypto/hash_provider/hash_sha1.c new file mode 100644 index 000000000..ffc073cf1 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/hash_provider/hash_sha1.c @@ -0,0 +1,57 @@ +/* + * 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; + unsigned int i; + + if (output->length != SHS_DIGESTSIZE) + return(KRB5_CRYPTO_INTERNAL); + + shsInit(&ctx); + for (i=0; idata[i*4]); + } + + return(0); +} + +const struct krb5_hash_provider krb5int_hash_sha1 = { + SHS_DIGESTSIZE, + SHS_DATASIZE, + k5_sha1_hash +}; diff --git a/krb5-1-7/src/lib/crypto/hmac.c b/krb5-1-7/src/lib/crypto/hmac.c new file mode 100644 index 000000000..c2ff3341c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/hmac.c @@ -0,0 +1,166 @@ +/* + * 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 "aead.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; + unsigned 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; ilength; i++) + xorkey[i] ^= key->contents[i]; + + /* compute the inner hash */ + + for (i=0; ihash))(icount+1, hashin, &hashout)))) + goto cleanup; + + /* create the outer padded key */ + + memset(xorkey, 0x5c, blocksize); + + for (i=0; ilength; 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); +} + +krb5_error_code +krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key, + const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_data *sign_data; + size_t num_sign_data; + krb5_error_code ret; + size_t i, j; + + /* Create a checksum over all the data to be signed */ + for (i = 0, num_sign_data = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + num_sign_data++; + } + + /* XXX cleanup to avoid alloc */ + sign_data = (krb5_data *)calloc(num_sign_data, sizeof(krb5_data)); + if (sign_data == NULL) + return ENOMEM; + + for (i = 0, j = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + sign_data[j++] = iov->data; + } + + /* caller must store checksum in iov as it may be TYPE_TRAILER or TYPE_CHECKSUM */ + ret = krb5_hmac(hash, key, num_sign_data, sign_data, output); + + free(sign_data); + + return ret; +} + diff --git a/krb5-1-7/src/lib/crypto/keyblocks.c b/krb5-1-7/src/lib/crypto/keyblocks.c new file mode 100644 index 000000000..5912c81b4 --- /dev/null +++ b/krb5-1-7/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 + +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); + free(val); +} + +void +krb5int_c_free_keyblock_contents(krb5_context context, krb5_keyblock *key) +{ + if (key && key->contents) { + krb5int_zap_data (key->contents, key->length); + free(key->contents); + key->contents = 0; + } +} diff --git a/krb5-1-7/src/lib/crypto/keyed_checksum_types.c b/krb5-1-7/src/lib/crypto/keyed_checksum_types.c new file mode 100644 index 000000000..04aa44757 --- /dev/null +++ b/krb5-1-7/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; i1length != 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? (const unsigned char *)ivec->data: + (const 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, + NULL, + NULL +}; diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/hmac_md5.c b/krb5-1-7/src/lib/crypto/keyhash_provider/hmac_md5.c new file mode 100644 index 000000000..34ce67169 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/hmac_md5.c @@ -0,0 +1,144 @@ +/* + * lib/crypto/keyhash_provider/hmac_md5.c + * + * Copyright 2001, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#include "../aead.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); + store_32_le(ms_usage, t); + 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; +} + +static krb5_error_code +k5_hmac_md5_hash_iov (const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *iv, + const krb5_crypto_iov *data, size_t num_data, + 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]; + size_t i; + + 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); + store_32_le(ms_usage, t); + krb5_MD5Update (&ctx, (unsigned char * ) &t, 4); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + krb5_MD5Update (&ctx, (unsigned char *)iov->data.data, + (unsigned int)iov->data.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*/ + k5_hmac_md5_hash_iov, + NULL /*checksum again */ +}; diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md4des.c b/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md4des.c new file mode 100644 index 000000000..fceb58ebd --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md4des.c @@ -0,0 +1,194 @@ +/* + * 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]; + unsigned 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; idata, + (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, (const 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]; + unsigned 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; idata, + (krb5_pointer) plaintext, hash->length, + schedule, + (const 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, + NULL, + NULL +}; diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md5des.c b/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md5des.c new file mode 100644 index 000000000..0175c68ab --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/k5_md5des.c @@ -0,0 +1,191 @@ +/* + * 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]; + unsigned 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; idata, + (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, (const 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]; + unsigned 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; idata, + (krb5_pointer) plaintext, hash->length, + schedule, + (const 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, + NULL, + NULL +}; diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/keyhash_provider.h b/krb5-1-7/src/lib/crypto/keyhash_provider/keyhash_provider.h new file mode 100644 index 000000000..8ac91e19d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/keyhash_provider.h @@ -0,0 +1,35 @@ +/* + * 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; +extern const struct krb5_keyhash_provider krb5int_keyhash_md5_hmac; +extern const struct krb5_keyhash_provider krb5int_keyhash_aescbc_128; +extern const struct krb5_keyhash_provider krb5int_keyhash_aescbc_256; diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/md5_hmac.c b/krb5-1-7/src/lib/crypto/keyhash_provider/md5_hmac.c new file mode 100644 index 000000000..d05b97f00 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/md5_hmac.c @@ -0,0 +1,65 @@ +/* + * lib/crypto/keyhash_provider/md5_hmac.c + * + * Copyright 2001, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 Microsoft KERB_CHECKSUM_MD5_HMAC + */ + +#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_md5_hmac_hash (const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *iv, + const krb5_data *input, krb5_data *output) +{ + krb5_keyusage ms_usage; + krb5_MD5_CTX ctx; + unsigned char t[4]; + krb5_data ds; + + krb5_MD5Init(&ctx); + + ms_usage = krb5int_arcfour_translate_usage (usage); + store_32_le(ms_usage, t); + krb5_MD5Update(&ctx, t, sizeof(t)); + krb5_MD5Update(&ctx, (unsigned char *)input->data, input->length); + krb5_MD5Final(&ctx); + + ds.magic = KV5M_DATA; + ds.length = 16; + ds.data = (char *)ctx.digest; + + return krb5_hmac ( &krb5int_hash_md5, key, 1, &ds, output); +} + +const struct krb5_keyhash_provider krb5int_keyhash_md5_hmac = { + 16, + k5_md5_hmac_hash, + NULL /*checksum again*/ +}; + diff --git a/krb5-1-7/src/lib/crypto/keyhash_provider/t_cksum.c b/krb5-1-7/src/lib/crypto/keyhash_provider/t_cksum.c new file mode 100644 index 000000000..24fd71917 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/keyhash_provider/t_cksum.c @@ -0,0 +1,180 @@ +/* + * 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; ilength; i++) + printf("%02x", (unsigned char) checksum->data[i]); + printf("\n"); +} + +static void +parse_hexstring(const char *s, krb5_data *dat) +{ + size_t i, len; + unsigned int byte; + unsigned char *cp; + + len = strlen(s); + cp = malloc(len / 2); + dat->data = (char *)cp; + if (cp == NULL) { + dat->length = 0; + return; + } + dat->length = len / 2; + for (i = 0; i + 1 < len; i += 2) { + sscanf(&s[i], "%2x", &byte); + *cp++ = byte; + } +} + +/* + * 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, knowncksum_dat; + + /* 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 + 1 < argc; msgindex += 2) { + 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"); + kret = 1; + 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"); + kret = 1; + break; + } + printf("Verify of bad checksum OK for \"%s\"\n", argv[msgindex]); + parse_hexstring(argv[msgindex+1], &knowncksum_dat); + if (knowncksum_dat.data == NULL) { + printf("parse_hexstring failed\n"); + kret = 1; + break; + } + if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &knowncksum_dat, + &valid))) { + printf("verify on known checksum choked with %d\n", kret); + break; + } + if (!valid) { + printf("verify on known checksum failed\n"); + kret = 1; + break; + } + printf("Verify on known checksum succeeded\n"); + kret = 0; + } + free(newstyle_checksum.data); + if (!kret) + printf("%d tests passed successfully for MD%d checksum\n", (argc-1)/2, MD); + + return(kret); +} diff --git a/krb5-1-7/src/lib/crypto/keylengths.c b/krb5-1-7/src/lib/crypto/keylengths.c new file mode 100644 index 000000000..acd1da81b --- /dev/null +++ b/krb5-1-7/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; ikeybytes; + if (keylength) + *keylength = krb5_enctypes_list[i].enc->keylength; + + return(0); +} diff --git a/krb5-1-7/src/lib/crypto/libk5crypto.exports b/krb5-1-7/src/lib/crypto/libk5crypto.exports new file mode 100644 index 000000000..4ea46fa19 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/libk5crypto.exports @@ -0,0 +1,162 @@ +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_fx_cf2_simple +krb5_c_checksum_length +krb5_c_crypto_length +krb5_c_crypto_length_iov +krb5_c_decrypt +krb5_c_decrypt_iov +krb5_c_encrypt +krb5_c_encrypt_iov +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_checksum_iov +krb5_c_make_random_key +krb5_c_padding_length +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_c_verify_checksum_iov +krb5_c_weak_enctype +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_free_keyblock +krb5int_c_free_keyblock_contents +krb5int_c_init_keyblock +krb5int_c_mandatory_cksumtype +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_hash_crc32 +krb5int_hash_md4 +krb5int_hash_md5 +krb5int_hash_sha1 +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-7/src/lib/crypto/make_checksum.c b/krb5-1-7/src/lib/crypto/make_checksum.c new file mode 100644 index 000000000..ad532b27d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/make_checksum.c @@ -0,0 +1,129 @@ +/* + * 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) +{ + unsigned int i; + int e1, e2; + krb5_data data; + krb5_error_code ret; + size_t cksumlen; + + for (i=0; ihashsize; + 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 */ + const struct krb5_keyhash_provider *keyhash; + + keyhash = krb5_cksumtypes_list[i].keyhash; + + if (krb5_cksumtypes_list[i].keyed_etype) { + for (e1=0; e1enctype) + 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; + } + } + + if (keyhash->hash == NULL) { + krb5_crypto_iov iov[1]; + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = *input; + + assert(keyhash->hash_iov != NULL); + + ret = (*keyhash->hash_iov)(key, usage, 0, iov, 1, &data); + } else { + ret = (*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-7/src/lib/crypto/make_checksum_iov.c b/krb5-1-7/src/lib/crypto/make_checksum_iov.c new file mode 100644 index 000000000..3cf4af605 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/make_checksum_iov.c @@ -0,0 +1,82 @@ +/* + * lib/crypto/make_checksum_iov.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "cksumtypes.h" +#include "aead.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *key, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + unsigned int i; + size_t cksumlen; + krb5_error_code ret; + krb5_data cksum_data; + krb5_crypto_iov *checksum; + + 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 != NULL) + cksum_data.length = krb5_cksumtypes_list[i].keyhash->hashsize; + else + cksum_data.length = krb5_cksumtypes_list[i].hash->hashsize; + + if (krb5_cksumtypes_list[i].trunc_size != 0) + cksumlen = krb5_cksumtypes_list[i].trunc_size; + else + cksumlen = cksum_data.length; + + checksum = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL || checksum->data.length < cksumlen) + return(KRB5_BAD_MSIZE); + + cksum_data.data = malloc(cksum_data.length); + if (cksum_data.data == NULL) + return(ENOMEM); + + ret = krb5int_c_make_checksum_iov(&krb5_cksumtypes_list[i], + key, usage, data, num_data, + &cksum_data); + if (ret == 0) { + memcpy(checksum->data.data, cksum_data.data, cksumlen); + checksum->data.length = cksumlen; + } + + free(cksum_data.data); + + return(ret); +} diff --git a/krb5-1-7/src/lib/crypto/make_random_key.c b/krb5-1-7/src/lib/crypto/make_random_key.c new file mode 100644 index 000000000..0ae321dca --- /dev/null +++ b/krb5-1-7/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; ikeybytes; + 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-7/src/lib/crypto/mandatory_sumtype.c b/krb5-1-7/src/lib/crypto/mandatory_sumtype.c new file mode 100644 index 000000000..f9322ff3f --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/md4/ISSUES b/krb5-1-7/src/lib/crypto/md4/ISSUES new file mode 100644 index 000000000..1103bd87b --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/md4/Makefile.in b/krb5-1-7/src/lib/crypto/md4/Makefile.in new file mode 100644 index 000000000..f7d65b818 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md4/Makefile.in @@ -0,0 +1,58 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/md4/deps b/krb5-1-7/src/lib/crypto/md4/deps new file mode 100644 index 000000000..775a8b446 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md4/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/md4/md4.c b/krb5-1-7/src/lib/crypto/md4/md4.c new file mode 100644 index 000000000..7922c71ed --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md4/md4.c @@ -0,0 +1,246 @@ +/* + * 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] = load_32_le(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] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* 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]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + 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-7/src/lib/crypto/md4/rsa-md4.h b/krb5-1-7/src/lib/crypto/md4/rsa-md4.h new file mode 100644 index 000000000..d4e6f6b79 --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/crypto/md5/ISSUES b/krb5-1-7/src/lib/crypto/md5/ISSUES new file mode 100644 index 000000000..481e52914 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/md5/Makefile.in b/krb5-1-7/src/lib/crypto/md5/Makefile.in new file mode 100644 index 000000000..73a4ceaee --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md5/Makefile.in @@ -0,0 +1,48 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/md5/deps b/krb5-1-7/src/lib/crypto/md5/deps new file mode 100644 index 000000000..131185443 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md5/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/md5/md5.c b/krb5-1-7/src/lib/crypto/md5/md5.c new file mode 100644 index 000000000..e548dbc3a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/md5/md5.c @@ -0,0 +1,343 @@ +/* + *********************************************************************** + ** 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] = load_32_le(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] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* 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]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + 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-7/src/lib/crypto/md5/rsa-md5.h b/krb5-1-7/src/lib/crypto/md5/rsa-md5.h new file mode 100644 index 000000000..846b23856 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/md5/t_cksum.c b/krb5-1-7/src/lib/crypto/md5/t_cksum.c new file mode 100644 index 000000000..17ecd51d7 --- /dev/null +++ b/krb5-1-7/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; ilength; 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-7/src/lib/crypto/md5/t_mddriver.c b/krb5-1-7/src/lib/crypto/md5/t_mddriver.c new file mode 100644 index 000000000..d894aaaec --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/nfold.c b/krb5-1-7/src/lib/crypto/nfold.c new file mode 100644 index 000000000..1f1902d1c --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/crypto/old/Makefile.in b/krb5-1-7/src/lib/crypto/old/Makefile.in new file mode 100644 index 000000000..7e68315f2 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/old/Makefile.in @@ -0,0 +1,35 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/old/deps b/krb5-1-7/src/lib/crypto/old/deps new file mode 100644 index 000000000..38a00ddf6 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/old/deps @@ -0,0 +1,34 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-7/src/lib/crypto/old/des_stringtokey.c b/krb5-1-7/src/lib/crypto/old/des_stringtokey.c new file mode 100644 index 000000000..2bacb4ef9 --- /dev/null +++ b/krb5-1-7/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 + +/* 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-7/src/lib/crypto/old/old.h b/krb5-1-7/src/lib/crypto/old/old.h new file mode 100644 index 000000000..94ee6421e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/old/old_decrypt.c b/krb5-1-7/src/lib/crypto/old/old_decrypt.c new file mode 100644 index 000000000..89d6a2a8d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/old/old_decrypt.c @@ -0,0 +1,145 @@ +/* + * 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; + + /* Verify input and output lengths. */ + if (input->length < blocksize + hashsize || input->length % blocksize != 0) + return(KRB5_BAD_MSIZE); + 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-7/src/lib/crypto/old/old_encrypt.c b/krb5-1-7/src/lib/crypto/old/old_encrypt.c new file mode 100644 index 000000000..98bd109e0 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/old_api_glue.c b/krb5-1-7/src/lib/crypto/old_api_glue.c new file mode 100644 index 000000000..4db0c3359 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/old_api_glue.c @@ -0,0 +1,328 @@ +/* + * 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); + key = NULL; + } + + *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-7/src/lib/crypto/pbkdf2.c b/krb5-1-7/src/lib/crypto/pbkdf2.c new file mode 100644 index 000000000..d897e9a71 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/pbkdf2.c @@ -0,0 +1,265 @@ +/* + * lib/crypto/pbkdf2.c + * + * Copyright 2002, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#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) { + unsigned 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; + unsigned 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. */ + store_32_be(i, ibytes); + + 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 ENOMEM; + utmp2 = /*utmp1 + hlen; */ malloc(salt->length + 4 + hlen); + if (utmp2 == NULL) { + free(utmp1); + return ENOMEM; + } + + /* 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-7/src/lib/crypto/prf.c b/krb5-1-7/src/lib/crypto/prf.c new file mode 100644 index 000000000..f52564db4 --- /dev/null +++ b/krb5-1-7/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 + +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; idata); + + + for (i=0; ienctype) + 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-7/src/lib/crypto/prng.c b/krb5-1-7/src/lib/crypto/prng.c new file mode 100644 index 000000000..f9647eae2 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/prng.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2001, 2002, 2004, 2007, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include "k5-thread.h" + +#include "yarrow.h" +static Yarrow_CTX y_ctx; +#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 +#endif +#ifdef HAVE_SYS_STAT_H +#include +#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; + set_cloexec_fd(fd); + if (fstat (fd, &sb) == -1 || 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-7/src/lib/crypto/random_to_key.c b/krb5-1-7/src/lib/crypto/random_to_key.c new file mode 100644 index 000000000..20f0abc0d --- /dev/null +++ b/krb5-1-7/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; ilength != 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-7/src/lib/crypto/raw/Makefile.in b/krb5-1-7/src/lib/crypto/raw/Makefile.in new file mode 100644 index 000000000..4a1d0376c --- /dev/null +++ b/krb5-1-7/src/lib/crypto/raw/Makefile.in @@ -0,0 +1,34 @@ +thisconfigdir=../../.. +myfulldir=lib/crypto/raw +mydir=lib/crypto/raw +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. +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 raw_aead.o + +OBJS= $(OUTPRE)raw_decrypt.$(OBJEXT) $(OUTPRE)raw_encrypt.$(OBJEXT) $(OUTPRE)raw_aead.$(OBJEXT) + +SRCS= $(srcdir)/raw_decrypt.c $(srcdir)/raw_encrypt.c $(srcdir)/raw_aead.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs + +includes:: depend + +depend:: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/crypto/raw/deps b/krb5-1-7/src/lib/crypto/raw/deps new file mode 100644 index 000000000..f80c49b48 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/raw/deps @@ -0,0 +1,34 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +raw_aead.so raw_aead.po $(OUTPRE)raw_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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)/../aead.h \ + $(srcdir)/../cksumtypes.h raw.h raw_aead.c diff --git a/krb5-1-7/src/lib/crypto/raw/raw.h b/krb5-1-7/src/lib/crypto/raw/raw.h new file mode 100644 index 000000000..f4b7d5f0b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/raw/raw.h @@ -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" + +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); + +extern const struct krb5_aead_provider krb5int_aead_raw; + diff --git a/krb5-1-7/src/lib/crypto/raw/raw_aead.c b/krb5-1-7/src/lib/crypto/raw/raw_aead.c new file mode 100644 index 000000000..f52fe000d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/raw/raw_aead.c @@ -0,0 +1,163 @@ +/* + * lib/crypto/raw/raw_aead.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "raw.h" +#include "aead.h" + +/* AEAD */ + +static krb5_error_code +krb5int_raw_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_PADDING: + *length = enc->block_size; + break; + default: + *length = 0; + break; + } + + return 0; +} + +static krb5_error_code +krb5int_raw_encrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *padding; + size_t i; + unsigned int blocksize = 0; + unsigned int plainlen = 0; + unsigned int padsize = 0; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize); + if (ret != 0) + return ret; + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + if (blocksize != 0) { + /* Check that the input data is correctly padded */ + if (plainlen % blocksize) + padsize = blocksize - (plainlen % blocksize); + } + + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padsize && (padding == NULL || padding->data.length < padsize)) + return KRB5_BAD_MSIZE; + + if (padding != NULL) { + memset(padding->data.data, 0, padsize); + padding->data.length = padsize; + } + + assert(enc->encrypt_iov != NULL); + + ret = enc->encrypt_iov(key, ivec, data, num_data); /* will update ivec */ + + return ret; +} + +static krb5_error_code +krb5int_raw_decrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + size_t i; + unsigned int blocksize = 0; /* careful, this is enc block size not confounder len */ + unsigned int cipherlen = 0; + + if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) { + return krb5int_c_iov_decrypt_stream(aead, enc, hash, key, + usage, ivec, data, num_data); + } + + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize); + if (ret != 0) + return ret; + + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_DATA_IOV(iov)) + cipherlen += iov->data.length; + } + + if (blocksize == 0) { + /* Check for correct input length in CTS mode */ + if (enc->block_size != 0 && cipherlen < enc->block_size) + return KRB5_BAD_MSIZE; + } else { + /* Check that the input data is correctly padded */ + if ((cipherlen % blocksize) != 0) + return KRB5_BAD_MSIZE; + } + + /* Validate header and trailer lengths */ + + /* derive the keys */ + + /* decrypt the plaintext (header | data | padding) */ + assert(enc->decrypt_iov != NULL); + + ret = enc->decrypt_iov(key, ivec, data, num_data); /* will update ivec */ + + return ret; +} + +const struct krb5_aead_provider krb5int_aead_raw = { + krb5int_raw_crypto_length, + krb5int_raw_encrypt_iov, + krb5int_raw_decrypt_iov +}; diff --git a/krb5-1-7/src/lib/crypto/raw/raw_decrypt.c b/krb5-1-7/src/lib/crypto/raw/raw_decrypt.c new file mode 100644 index 000000000..bfa8e281d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/raw/raw_decrypt.c @@ -0,0 +1,40 @@ +/* + * 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) +{ + if (output->length < input->length) + return KRB5_BAD_MSIZE; + return((*(enc->decrypt))(key, ivec, input, output)); +} diff --git a/krb5-1-7/src/lib/crypto/raw/raw_encrypt.c b/krb5-1-7/src/lib/crypto/raw/raw_encrypt.c new file mode 100644 index 000000000..68b819c01 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/sha1/ISSUES b/krb5-1-7/src/lib/crypto/sha1/ISSUES new file mode 100644 index 000000000..8b7e8a2a1 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/sha1/Makefile.in b/krb5-1-7/src/lib/crypto/sha1/Makefile.in new file mode 100644 index 000000000..ffa314d1f --- /dev/null +++ b/krb5-1-7/src/lib/crypto/sha1/Makefile.in @@ -0,0 +1,53 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/sha1/deps b/krb5-1-7/src/lib/crypto/sha1/deps new file mode 100644 index 000000000..e8f519a9e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/sha1/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/sha1/shs.c b/krb5-1-7/src/lib/crypto/sha1/shs.c new file mode 100644 index 000000000..d9372df39 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/sha1/shs.c @@ -0,0 +1,381 @@ +#include "shs.h" +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include + +/* 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)); + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + { + 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; + unsigned int dataCount; + int 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 = (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++ = load_32_be(buffer); + buffer += 4; + 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++ = load_32_be(buffer); + buffer += 4; + } + SHSTransform(shsInfo->digest, shsInfo->data); + count -= SHS_DATASIZE; + } + + if (count > 0) { + lp = shsInfo->data; + while (count > 4) { + *lp++ = load_32_be(buffer); + buffer += 4; + 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-7/src/lib/crypto/sha1/shs.h b/krb5-1-7/src/lib/crypto/sha1/shs.h new file mode 100644 index 000000000..6dcb41b40 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/sha1/t_shs.c b/krb5-1-7/src/lib/crypto/sha1/t_shs.c new file mode 100644 index 000000000..adcb0927a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/sha1/t_shs.c @@ -0,0 +1,135 @@ +/**************************************************************************** +* * +* SHS Test Code * +* * +****************************************************************************/ + +#include +#include +#include +#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-7/src/lib/crypto/sha1/t_shs3.c b/krb5-1-7/src/lib/crypto/sha1/t_shs3.c new file mode 100644 index 000000000..96b36a76e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/sha1/t_shs3.c @@ -0,0 +1,592 @@ +/* test shs code */ + +#include +#include +#include +#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-7/src/lib/crypto/state.c b/krb5-1-7/src/lib/crypto/state.c new file mode 100644 index 000000000..f69746c81 --- /dev/null +++ b/krb5-1-7/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; ienctype) + 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; ienctype) + break; + } + + if (i == krb5_enctypes_length) + return(KRB5_BAD_ENCTYPE); + + return (*(krb5_enctypes_list[i].enc->free_state)) + (state); +} diff --git a/krb5-1-7/src/lib/crypto/string_to_cksumtype.c b/krb5-1-7/src/lib/crypto/string_to_cksumtype.c new file mode 100644 index 000000000..5a3c70d73 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/string_to_cksumtype.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_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep) +{ + unsigned int i, j; + + for (i=0; ilength == 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); + key->length = 0; + key->contents = NULL; + } + + return(ret); +} diff --git a/krb5-1-7/src/lib/crypto/t_cf2.c b/krb5-1-7/src/lib/crypto/t_cf2.c new file mode 100644 index 000000000..2e171c275 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_cf2.c @@ -0,0 +1,88 @@ +/* + * lib/crypto/t_cf2.c + * + * Copyright (C) 2004, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 theKRB-FX-CF2 code in Kerberos, based + *on the PRF regression tests. 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. + *First line: enctype + *second line: key to pass to string2key; also used as salt + *Third line: second key to pass to string2key + *fourth line: pepper1 + *fifth line: pepper2 + *scanf is used to read the file, so interior spaces are not permitted. The program outputs the hex bytes of the key. + */ +#include + +#include +#include +#include + +int main () { + char pepper1[1024], pepper2[1024]; + krb5_keyblock *k1 = NULL, *k2 = NULL, *out = NULL; + krb5_data s2k; + 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, &k1) == 0); + s2k.data = &s[0]; + s2k.length = strlen(s); + assert(krb5_c_string_to_key (0, enctype, &s2k, &s2k, k1) == 0); + if (scanf("%1024s", &s[0]) == EOF) + break; + assert (krb5_init_keyblock(0, enctype, 0, &k2) == 0); + s2k.data = &s[0]; + s2k.length = strlen(s); + assert(krb5_c_string_to_key (0, enctype, &s2k, &s2k, k2) == 0); + if (scanf("%1024s %1024s", pepper1, pepper2) == EOF) + break; + assert(krb5_c_fx_cf2_simple(0, k1, pepper1, + k2, pepper2, &out) ==0); + i = out->length; + for (; i > 0; i--) { + printf ("%02x", + (unsigned int) ((unsigned char) out->contents[out->length-i])); + } + printf ("\n"); + + krb5_free_keyblock(0,out); + out = NULL; + + krb5_free_keyblock(0, k1); + k1 = NULL; + krb5_free_keyblock(0, k2); + k2 = NULL; + } + + return (0); +} diff --git a/krb5-1-7/src/lib/crypto/t_cf2.comments b/krb5-1-7/src/lib/crypto/t_cf2.comments new file mode 100644 index 000000000..504dc3173 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_cf2.comments @@ -0,0 +1,5 @@ +The first test mirrors the first two tests in t_prf.in. + +The second test mirrors the following four tests in t_prf.in. + +The third and fourth tests are simple tests of the DES and 3DES PRF. diff --git a/krb5-1-7/src/lib/crypto/t_cf2.expected b/krb5-1-7/src/lib/crypto/t_cf2.expected new file mode 100644 index 000000000..709791121 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_cf2.expected @@ -0,0 +1,4 @@ +97df97e4b798b29eb31ed7280287a92a +4d6ca4e629785c1f01baf55e2e548566b9617ae3a96868c337cb93b5e72b1c7b +43bae3738c9467e6 +e58f9eb643862c13ad38e529313462a7f73e62834fe54a01 diff --git a/krb5-1-7/src/lib/crypto/t_cf2.in b/krb5-1-7/src/lib/crypto/t_cf2.in new file mode 100644 index 000000000..b951e4c0e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_cf2.in @@ -0,0 +1,20 @@ +17 +key1 +key2 +a +b +18 +key1 +key2 +a +b +1 +key1 +key2 +a +b +16 +key1 +key2 +a +b diff --git a/krb5-1-7/src/lib/crypto/t_cts.c b/krb5-1-7/src/lib/crypto/t_cts.c new file mode 100644 index 000000000..aef813273 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_cts.c @@ -0,0 +1,176 @@ +/* + * lib/crypto/vectors.c + * + * Copyright 2001, 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. + * + * + * 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 +#include +#include +#include +#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 (!data_eq(out2, in)) { + 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-7/src/lib/crypto/t_encrypt.c b/krb5-1-7/src/lib/crypto/t_encrypt.c new file mode 100644 index 000000000..974dc585b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_encrypt.c @@ -0,0 +1,214 @@ +/* + * lib/crypto/t_encrypt.c + * + * Copyright 2001, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +/* 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 +}; + +static void +test(const char *msg, krb5_error_code retval) +{ + printf("%s: . . . ", msg); + 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; + krb5_crypto_iov iov[5]; + int i; + size_t len; + krb5_enc_data enc_out, enc_out2; + krb5_error_code retval; + krb5_keyblock *key; + + memset(iov, 0, sizeof(iov)); + + 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)); + if ( krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_HEADER, &len) == 0 ){ + /* We support iov/aead*/ + int j, pos; + krb5_data signdata; + signdata.data = (char *) "This should be signed"; + signdata.length = strlen(signdata.data); + iov[0].flags= KRB5_CRYPTO_TYPE_STREAM; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = enc_out.ciphertext; + iov[1].data = out; + test("IOV stream decrypting", + krb5_c_decrypt_iov( context, key, 7, 0, iov, 2)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = in; /*We'll need to copy memory before encrypt*/ + iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + iov[2].data = signdata; + iov[3].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER; + test("Setting up iov lengths", + krb5_c_crypto_length_iov(context, key->enctype, iov, 5)); + for (j=0,pos=0; j <= 4; j++ ){ + if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + iov[j].data.data = &out.data[pos]; + pos += iov[j].data.length; + } + assert (iov[1].data.length == in.length); + memcpy(iov[1].data.data, in.data, in.length); + test("iov encrypting", + krb5_c_encrypt_iov(context, key, 7, 0, iov, 5)); + assert(iov[1].data.length == in.length); + test("iov decrypting", + krb5_c_decrypt_iov(context, key, 7, 0, iov, 5)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + } + 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); + } + + /* Test the RC4 decrypt fallback from key usage 9 to 8. */ + test ("Initializing an RC4 keyblock", + krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &key)); + test ("Generating random RC4 key", + krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, key)); + enc_out.ciphertext = out; + krb5_c_encrypt_length (context, key->enctype, in.length, &len); + enc_out.ciphertext.length = len; + check.length = 2048; + test ("Encrypting with RC4 key usage 8", + krb5_c_encrypt (context, key, 8, 0, &in, &enc_out)); + test ("Decrypting with RC4 key usage 9", + krb5_c_decrypt (context, key, 9, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + free(out.data); + free(out2.data); + free(check.data); + free(check2.data); + return 0; +} + + diff --git a/krb5-1-7/src/lib/crypto/t_hmac.c b/krb5-1-7/src/lib/crypto/t_hmac.c new file mode 100644 index 000000000..bf629c359 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_hmac.c @@ -0,0 +1,273 @@ +/* + * 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 +#include +#include +#include + +#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; + struct k5buf buf; + + /* 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); + } + + krb5int_buf_init_fixed(&buf, stroutbuf, sizeof(stroutbuf)); + krb5int_buf_add(&buf, "0x"); + for (j = 0; j < out.length; j++) + krb5int_buf_add_fmt(&buf, "%02x", 0xff & outbuf[j]); + if (krb5int_buf_data(&buf) == NULL) + abort(); + 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-7/src/lib/crypto/t_nfold.c b/krb5-1-7/src/lib/crypto/t_nfold.c new file mode 100644 index 000000000..6be0a0934 --- /dev/null +++ b/krb5-1-7/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 +#include +#include + +#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 +#include +#include +#include + +#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-7/src/lib/crypto/t_prf.c b/krb5-1-7/src/lib/crypto/t_prf.c new file mode 100644 index 000000000..ac244eb9a --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prf.c @@ -0,0 +1,91 @@ +/* + * 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 password 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 + +int main () { + krb5_data input, output; + krb5_keyblock *key = NULL; + unsigned int in_length; + unsigned int i; + size_t prfsz; + + 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, &prfsz) == 0); + assert (output.data = malloc(prfsz)); + output.length = prfsz; + assert (krb5_c_prf(0, key, &input, &output) == 0); + + free (input.data); + input.data = NULL; + } + for (; prfsz > 0; prfsz--) { + printf ("%02x", + (unsigned int) ((unsigned char ) output.data[output.length-prfsz])); + } + printf ("\n"); + + free (output.data); + output.data = NULL; + krb5_free_keyblock(0, key); + key = NULL; + } + + return (0); +} diff --git a/krb5-1-7/src/lib/crypto/t_prf.comments b/krb5-1-7/src/lib/crypto/t_prf.comments new file mode 100644 index 000000000..124584259 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prf.comments @@ -0,0 +1,8 @@ +The first two tests are effectively a call to krb-fx-cf2 for +aes-128-cts. This mirrorrs the first test in t_cf2.in. + + +The next four tests mirror a call to KRB-FX-CF2 for aes256-cts; this +mirrors the second test in t_cf2.in. + + diff --git a/krb5-1-7/src/lib/crypto/t_prf.expected b/krb5-1-7/src/lib/crypto/t_prf.expected new file mode 100644 index 000000000..eadfd9747 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prf.expected @@ -0,0 +1,6 @@ +77b39a37a868920f2a51f9dd150c5717 +e06c0dd31ff02091994f2ef5178bfe3d +b2628c788e2e9c4a9bb4644678c29f2f +b406373350cee8a6126f4a9b65a0cd21 +ff0e289ea756c0559a0e911856961a49 +0d674dd0f9a6806525a4d92e828bd15a diff --git a/krb5-1-7/src/lib/crypto/t_prf.in b/krb5-1-7/src/lib/crypto/t_prf.in new file mode 100644 index 000000000..f45c41618 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prf.in @@ -0,0 +1,18 @@ +17 +key1 +2 0161 +17 +key2 +2 0162 +18 +key1 +2 0161 +18 +key1 +2 0261 +18 +key2 +2 0162 +18 +key2 +2 0262 diff --git a/krb5-1-7/src/lib/crypto/t_prng.c b/krb5-1-7/src/lib/crypto/t_prng.c new file mode 100644 index 000000000..49c0aec74 --- /dev/null +++ b/krb5-1-7/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 + +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-7/src/lib/crypto/t_prng.comments b/krb5-1-7/src/lib/crypto/t_prng.comments new file mode 100644 index 000000000..1666b7060 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/t_prng.expected b/krb5-1-7/src/lib/crypto/t_prng.expected new file mode 100644 index 000000000..f7f165051 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prng.expected @@ -0,0 +1,4 @@ +d2f8fbd707a8ece5cb11a02f +eb4cb6e06236ea1c0529f7acbfca8d78cb85bb1d +a244005ae870604342b0386025874ec4306c1dd483c118621b +63e6408afdf9fd225839a7afcc6da6ae494fb4f82bd21ea06bb17ca0848bdae8cea671f545aac52699951caba960c536024b4102f47d61d61fd7b17582a4cf50ba7d215062558f71483249e079689893f3bf25def7f45f9e852281269904d401d6719e3115f6410088c6c5171e878494362684d2116633bb9ea8d9ed5faec73cb076c44d5d639bc2c8ae3de54f0e1e092d5ea439e607e9cd73053bbdf40723f5b48f298fdeeef845e22e06f2f6362fc67fba366e638a7988999d456dcc3d53b23388d685620a7c446d28cd94b13049761b64779db5412e78ac4bab2aacf103fd1b9ceb7213d43710d6a46fd4223fa20e0a68d3e16a82cbadea650ba815dc9ee99b4eb8e2acdac866a05d90ab9de3246db0560fb4b36633bb642c3ea9bf358937dda743f9cef1148791c2cac58995b8eb8fdb1c0cce1686e04ebef5ae7aae36691faafbe8920d3c013f125b687eb019faefa70fc750c52e2e2e33f426824bf1da31268a9bb8d9501f2290375755f8bf77b46639346b4011b78ce9d81105c7791ec5991a2f1eab037488b604df1a21c5c4e36a7c76dca5884d36e30fe8d30d0e7d93fab72062219390655eace2b434b0e2cd21ec9c5a8aa13e783afadcdf386fc43b960c518acb38d7e3da2f67695c1c1c25c4f251b40f4c2e42e89f6f642c32e66159f6ce24aa910fb5d95e3a899a4de5efcf570996e1a662d14362b65d00524df79cd56be93bd572526e4dfd1cf9f7586bc021105cf5456b28c1f45a6d354d000a113e15f64aa0b5253830c07afc8fa47b58dbba8bbae1645b2093035f2387036229dec6f7141b444b8bb7d0382a742bd5c746ba2d7af3af1cadb2dd90bda87d5daed2d2eebd243c7b2d06955d0cc7fe1061d4cfa3b061aaeb97084d9f9a7ec9dbe9e642f4f090d57b5ea1bd8b393f00896d3dc7089e1fc4c2fed7336c2a8c6d119a682c6cc4ae1ccedd30292f2c5570bf4d6287ce8e20b8b34e7fc38e87273f588cd33b8c913defaee5f6bf8fdeda72531c845a6f97a84d5e9b9a6497d4c48614dee7693df35faedc008fded852be8d4bffd475476336e54ed48a827b99d3f0e39019a40d43aef5ae522ec6e280f6a8e7d2713f3c3188bed2476a84af5a5afefa0fa178ed07de0e073693e8790f8bbd0cf9183e48f140b556e723565c382cf7a4c186748189a14e603e4ac70e2b80c266334231207721d16d834a973b48cfec584620624686603cfd66d55dbf8dd8eccd99d85f041c624ec3a7bec314af95d2313afd43cc5cc19249cf85b7ab0b5a4530b597341e7477b249fef1a07eb0d8fa790e9bce752e8b2f7086e98ab44751e0a1b37f29682ce67c0de7a2fd036f26ed719fc343bbf49432aec651d884c99c24d5943c747f7ec3b48d4c2236a8cb6151794daeda073774cc88ff121fdd423b81ef2f34c8f281ca2e5366faee87ff7a623484f2937cc0680ed76ead32b43cb6c67a21f8089b435f38a404d267397c6435cfac16591a3573d9e92f8c4a8028719c22662b903ddb16e08ea7bb2d6b8938c06bdddb4d174c7f2c5d812ed3a34ba8859a1ae841b3b9d5522372018c9aa55b048df826f05a087f185808cb66899f320783a1c4aa2dcd5f2665405ba7e5726e122b67559a39da30956e49fe7711d1b2506e159c5ea42ce0a1ad497220ee3b3e5ebcb73db975bd08e8be56e5f4533b8295b10d4b0fef466de6540f8fe10530c9716d83a12f5ffbba5b4dbc50ed89388d04e7a15d3d9d251041ed5303efa2525bc62a5aeb821f7838676811784584534be8a7fc667f09c3fe1bbf7d0aad29324f562086ecb8326829413867 diff --git a/krb5-1-7/src/lib/crypto/t_prng.reseedtest b/krb5-1-7/src/lib/crypto/t_prng.reseedtest new file mode 100644 index 000000000..5eee0c064 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/t_prng.reseedtest-comments b/krb5-1-7/src/lib/crypto/t_prng.reseedtest-comments new file mode 100644 index 000000000..e50e09602 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/t_prng.reseedtest-expected b/krb5-1-7/src/lib/crypto/t_prng.reseedtest-expected new file mode 100644 index 000000000..d7b50801e --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_prng.reseedtest-expected @@ -0,0 +1 @@ +fd543f42aded9bd725c9b05682cd0f504c1b33d1 diff --git a/krb5-1-7/src/lib/crypto/t_prng.seed b/krb5-1-7/src/lib/crypto/t_prng.seed new file mode 100644 index 000000000..79f4f6458 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/t_short.c b/krb5-1-7/src/lib/crypto/t_short.c new file mode 100644 index 000000000..9ddfd5e3d --- /dev/null +++ b/krb5-1-7/src/lib/crypto/t_short.c @@ -0,0 +1,126 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * lib/crypto/crypto_tests/t_short.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Tests the outcome of decrypting overly short tokens. This program can be + * run under a tool like valgrind to detect bad memory accesses; when run + * normally by the test suite, it verifies that each operation returns + * KRB5_BAD_MSIZE. + */ + +#include "k5-int.h" + +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 +}; + +/* Abort if an operation unexpectedly fails. */ +static void +x(krb5_error_code code) +{ + if (code != 0) + abort(); +} + +/* Abort if a decrypt operation doesn't have the expected result. */ +static void +check_decrypt_result(krb5_error_code code, size_t len, size_t min_len) +{ + if (len < min_len) { + /* Undersized tokens should always result in BAD_MSIZE. */ + if (code != KRB5_BAD_MSIZE) + abort(); + } else { + /* Min-size tokens should succeed or fail the integrity check. */ + if (code != 0 && code != KRB5KRB_AP_ERR_BAD_INTEGRITY) + abort(); + } +} + +static void +test_enctype(krb5_enctype enctype) +{ + krb5_error_code ret; + krb5_keyblock keyblock; + krb5_enc_data input; + krb5_data output; + krb5_crypto_iov iov[2]; + unsigned int dummy; + size_t min_len, len; + + printf("Testing enctype %d\n", (int) enctype); + x(krb5_c_encrypt_length(NULL, enctype, 0, &min_len)); + x(krb5_c_make_random_key(NULL, enctype, &keyblock)); + input.enctype = enctype; + + /* Try each length up to the minimum length. */ + for (len = 0; len <= min_len; len++) { + input.ciphertext.data = calloc(len, 1); + input.ciphertext.length = len; + output.data = calloc(len, 1); + output.length = len; + + /* Attempt a normal decryption. */ + ret = krb5_c_decrypt(NULL, &keyblock, 0, NULL, &input, &output); + check_decrypt_result(ret, len, min_len); + + if (krb5_c_crypto_length(NULL, enctype, KRB5_CRYPTO_TYPE_HEADER, + &dummy) == 0) { + /* Attempt an IOV stream decryption. */ + iov[0].flags = KRB5_CRYPTO_TYPE_STREAM; + iov[0].data = input.ciphertext; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = NULL; + iov[1].data.length = 0; + ret = krb5_c_decrypt_iov(NULL, &keyblock, 0, NULL, iov, 2); + check_decrypt_result(ret, len, min_len); + } + + free(input.ciphertext.data); + free(output.data); + } +} + +int +main(int argc, char **argv) +{ + int i; + krb5_data notrandom; + + notrandom.data = "notrandom"; + notrandom.length = 9; + krb5_c_random_seed(NULL, ¬random); + for (i = 0; interesting_enctypes[i]; i++) + test_enctype(interesting_enctypes[i]); + return 0; +} diff --git a/krb5-1-7/src/lib/crypto/valid_cksumtype.c b/krb5-1-7/src/lib/crypto/valid_cksumtype.c new file mode 100644 index 000000000..8fd9effc9 --- /dev/null +++ b/krb5-1-7/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) +{ + unsigned int i; + + for (i=0; ietype == etype && (k->flags & ETYPE_WEAK)) { + return(1); + } + } + + return(0); +} diff --git a/krb5-1-7/src/lib/crypto/vectors.c b/krb5-1-7/src/lib/crypto/vectors.c new file mode 100644 index 000000000..64a5071c0 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#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)); + snprintf (buf, sizeof (buf), "\"%s\"", s); + printf ( "salt: %-25s", buf); + printhex (strlen(s), s); + snprintf (buf, sizeof (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)); + snprintf (buf, sizeof(buf), "\"%s\"", s); + printf ( "salt:\t%s\n\t", buf); + printhex (strlen(s), s); + snprintf (buf, sizeof(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-7/src/lib/crypto/verify_checksum.c b/krb5-1-7/src/lib/crypto/verify_checksum.c new file mode 100644 index 000000000..72b5595de --- /dev/null +++ b/krb5-1-7/src/lib/crypto/verify_checksum.c @@ -0,0 +1,92 @@ +/* + * 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) +{ + unsigned int i; + size_t hashsize; + krb5_error_code ret; + krb5_data indata; + krb5_checksum computed; + + for (i=0; ichecksum_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) { + const struct krb5_keyhash_provider *keyhash; + + keyhash = krb5_cksumtypes_list[i].keyhash; + + if (keyhash->verify == NULL && keyhash->verify_iov != NULL) { + krb5_crypto_iov iov[1]; + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = *data; + + return (*keyhash->verify_iov)(key, usage, 0, iov, 1, &indata, valid); + } else if (keyhash->verify != NULL) { + return (*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-7/src/lib/crypto/verify_checksum_iov.c b/krb5-1-7/src/lib/crypto/verify_checksum_iov.c new file mode 100644 index 000000000..08c0a5c7b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/verify_checksum_iov.c @@ -0,0 +1,98 @@ +/* + * lib/crypto/verify_checksum_iov.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "cksumtypes.h" +#include "aead.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + unsigned int i; + size_t cksumlen; + krb5_error_code ret; + krb5_data computed; + krb5_crypto_iov *checksum; + + for (i = 0; i < krb5_cksumtypes_length; i++) { + if (krb5_cksumtypes_list[i].ctype == checksum_type) + break; + } + + if (i == krb5_cksumtypes_length) + return(KRB5_BAD_ENCTYPE); + + checksum = krb5int_c_locate_iov((krb5_crypto_iov *)data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL) + return(KRB5_BAD_MSIZE); + + /* if there's actually a verify function, call it */ + + if (krb5_cksumtypes_list[i].keyhash && + krb5_cksumtypes_list[i].keyhash->verify_iov) + return((*(krb5_cksumtypes_list[i].keyhash->verify_iov))(key, usage, 0, + data, num_data, + &checksum->data, + valid)); + + /* otherwise, make the checksum again, and compare */ + + if (krb5_cksumtypes_list[i].keyhash != NULL) + computed.length = krb5_cksumtypes_list[i].keyhash->hashsize; + else + computed.length = krb5_cksumtypes_list[i].hash->hashsize; + + if (krb5_cksumtypes_list[i].trunc_size != 0) + cksumlen = krb5_cksumtypes_list[i].trunc_size; + else + cksumlen = computed.length; + + if (checksum->data.length != cksumlen) + return(KRB5_BAD_MSIZE); + + computed.data = malloc(computed.length); + if (computed.data == NULL) + return(ENOMEM); + + if ((ret = krb5int_c_make_checksum_iov(&krb5_cksumtypes_list[i], key, usage, + data, num_data, &computed))) { + free(computed.data); + return(ret); + } + + *valid = (computed.length == cksumlen) && + (memcmp(computed.data, checksum->data.data, cksumlen) == 0); + + free(computed.data); + + return(0); +} diff --git a/krb5-1-7/src/lib/crypto/yarrow/ASSUMPTIONS b/krb5-1-7/src/lib/crypto/yarrow/ASSUMPTIONS new file mode 100644 index 000000000..3e3c99c49 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/LICENSE b/krb5-1-7/src/lib/crypto/yarrow/LICENSE new file mode 100644 index 000000000..c85475d7e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/Makefile.in b/krb5-1-7/src/lib/crypto/yarrow/Makefile.in new file mode 100644 index 000000000..12d95860b --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/Makefile.in @@ -0,0 +1,39 @@ +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@ + diff --git a/krb5-1-7/src/lib/crypto/yarrow/README b/krb5-1-7/src/lib/crypto/yarrow/README new file mode 100644 index 000000000..3dd4b801a --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/TODO b/krb5-1-7/src/lib/crypto/yarrow/TODO new file mode 100644 index 000000000..bd133ecfd --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/deps b/krb5-1-7/src/lib/crypto/yarrow/deps new file mode 100644 index 000000000..182fa52d8 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/deps @@ -0,0 +1,25 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-7/src/lib/crypto/yarrow/yarrow.c b/krb5-1-7/src/lib/crypto/yarrow/yarrow.c new file mode 100644 index 000000000..e1f2ecdc6 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/yarrow.c @@ -0,0 +1,958 @@ +/* -*- 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 +#include +#ifdef _WIN32 +#include "port-sockets.h" +#else +# include +# include +#endif +#if !defined(YARROW_NO_MATHLIB) +#include +#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 +#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: + if ( y ) + { + 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-7/src/lib/crypto/yarrow/yarrow.h b/krb5-1-7/src/lib/crypto/yarrow/yarrow.h new file mode 100644 index 000000000..7e1fe1442 --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/crypto/yarrow/yarrow.man b/krb5-1-7/src/lib/crypto/yarrow/yarrow.man new file mode 100644 index 000000000..a65b4e05c --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/yarrow.pod b/krb5-1-7/src/lib/crypto/yarrow/yarrow.pod new file mode 100644 index 000000000..7892ebbe6 --- /dev/null +++ b/krb5-1-7/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 structure. B 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 if the +PRNG is seeded on exit, or B 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. The function assigns a unique number to the new source, +and places it in B. + +Yarrow_Poll() gathers entropy from the state of the machine and adds +it to the source B. The source has to be allocated by the +user with Yarrow_New_Source. Returns B if the PRNG is +seeded on exit, or B if the PRNG is not yet seeded. + +Yarrow_Input() is used to add randomness from the source B +to the PRNG. It reads B bytes at the address B. An +estimate of the entropy in bits contained in the sample must be +specified as B. + +Yarrow_Status() returns B if the PRNG has enough entropy to +produce output, and B 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 bytes of cryptographically strong +pseudo-random output and places them at B. 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. 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 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-7/src/lib/crypto/yarrow/ycipher.c b/krb5-1-7/src/lib/crypto/yarrow/ycipher.c new file mode 100644 index 000000000..2af410440 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/ycipher.c @@ -0,0 +1,96 @@ +/* + * lib/crypto/yarrow/ycipher.c + * + * Copyright (C) 2001, 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. + * + * + * + * 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 = (char *) 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-7/src/lib/crypto/yarrow/ycipher.h b/krb5-1-7/src/lib/crypto/yarrow/ycipher.h new file mode 100644 index 000000000..96999c0db --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/yexcep.h b/krb5-1-7/src/lib/crypto/yarrow/yexcep.h new file mode 100644 index 000000000..d27de2d5e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/yhash.h b/krb5-1-7/src/lib/crypto/yarrow/yhash.h new file mode 100644 index 000000000..ee4f03eb2 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/yhash.h @@ -0,0 +1,29 @@ +/* -*- 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++) \ + store_32_be(ctx->digest[loopvar], &out2[loopvar*4]); \ + } while(0) + + +#define HASH_DIGEST_SIZE SHS_DIGESTSIZE + +#endif /* YHASH_H */ diff --git a/krb5-1-7/src/lib/crypto/yarrow/ylock.h b/krb5-1-7/src/lib/crypto/yarrow/ylock.h new file mode 100644 index 000000000..9c032dc61 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/ystate.h b/krb5-1-7/src/lib/crypto/yarrow/ystate.h new file mode 100644 index 000000000..2886ca338 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/crypto/yarrow/ytest.c b/krb5-1-7/src/lib/crypto/yarrow/ytest.c new file mode 100644 index 000000000..93fb5f25a --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#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-7/src/lib/crypto/yarrow/ytypes.h b/krb5-1-7/src/lib/crypto/yarrow/ytypes.h new file mode 100644 index 000000000..9265e5a84 --- /dev/null +++ b/krb5-1-7/src/lib/crypto/yarrow/ytypes.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; c-file-style: "bsd" -*- */ + +#ifndef YTYPES_H +#define YTYPES_H + +#include +#include +#include "autoconf.h" +#ifdef HAVE_SYS_TYPES_H +#include +#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-7/src/lib/deps b/krb5-1-7/src/lib/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/lib/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/lib/glue4.c b/krb5-1-7/src/lib/glue4.c new file mode 100644 index 000000000..bf9bbd8a0 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/LICENSE b/krb5-1-7/src/lib/gssapi/LICENSE new file mode 100644 index 000000000..612f8ad6e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/Makefile.in b/krb5-1-7/src/lib/gssapi/Makefile.in new file mode 100644 index 000000000..f72a0d386 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/Makefile.in @@ -0,0 +1,137 @@ +thisconfigdir=../.. +myfulldir=lib/gssapi +mydir=lib/gssapi +BUILDTOP=$(REL)..$(S).. +SUBDIRS= generic krb5 spnego mechglue +DEFS=-D_GSS_STATIC_LINK=1 + +##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= + +OBJS= +SRCS= + +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: clean-recurse + $(RM) merged-gssapi-header.h + $(RM) -r $(EHDRDIR) + +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@ + diff --git a/krb5-1-7/src/lib/gssapi/README_SAMPLE_APP b/krb5-1-7/src/lib/gssapi/README_SAMPLE_APP new file mode 100644 index 000000000..c26bb09ad --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/deps b/krb5-1-7/src/lib/gssapi/deps new file mode 100644 index 000000000..2feac3c9d --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1-7/src/lib/gssapi/generic/Makefile.in b/krb5-1-7/src/lib/gssapi/generic/Makefile.in new file mode 100644 index 000000000..c35bd1abb --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/Makefile.in @@ -0,0 +1,173 @@ +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 \ + $(EHDRDIR)$(S)gssapi_ext.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)gssapi_ext.h: $(EHDRDIR)$(S)timestamp $(srcdir)$(S)gssapi_ext.h + $(CP) $(srcdir)$(S)gssapi_ext.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)/oid_ops.c \ + $(srcdir)/rel_buffer.c \ + $(srcdir)/rel_oid_set.c \ + $(srcdir)/util_buffer.c \ + $(srcdir)/util_buffer_set.c \ + $(srcdir)/util_errmap.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)oid_ops.$(OBJEXT) \ + $(OUTPRE)rel_buffer.$(OBJEXT) \ + $(OUTPRE)rel_oid_set.$(OBJEXT) \ + $(OUTPRE)util_buffer.$(OBJEXT) \ + $(OUTPRE)util_buffer_set.$(OBJEXT) \ + $(OUTPRE)util_errmap.$(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 \ + oid_ops.o \ + rel_buffer.o \ + rel_oid_set.o \ + util_buffer.o \ + util_buffer_set.o \ + util_errmap.o \ + util_ordering.o \ + util_set.o \ + util_token.o \ + util_validate.o \ + gssapi_err_generic.o + +EXPORTED_HEADERS= gssapi_generic.h gssapi_ext.h +EXPORTED_BUILT_HEADERS= gssapi.h + +$(OBJS): $(EXPORTED_HEADERS) $(ETHDRS) + +all-unix:: $(EXPORTED_HEADERS) $(ETHDRS) $(HDRS) +all-unix:: all-libobjs + +errmap.h: $(SRCTOP)/util/gen.pl $(SRCTOP)/util/t_array.pm \ + $(SRCTOP)/util/t_bimap.pm + $(PERL) -w -I$(SRCTOP)/util $(SRCTOP)/util/gen.pl bimap errmap.h \ + NAME=mecherrmap LEFT=OM_uint32 RIGHT="struct mecherror" \ + LEFTPRINT=print_OM_uint32 RIGHTPRINT=mecherror_print \ + LEFTCMP=cmp_OM_uint32 RIGHTCMP=mecherror_cmp + +maptest.h: $(SRCTOP)/util/gen.pl $(SRCTOP)/util/t_array.pm \ + $(SRCTOP)/util/t_bimap.pm + $(PERL) -w -I$(SRCTOP)/util $(SRCTOP)/util/gen.pl bimap maptest.h \ + NAME=foo LEFT=int RIGHT=elt LEFTPRINT=intprt RIGHTPRINT=eltprt \ + LEFTCMP=intcmp RIGHTCMP=eltcmp +maptest.o: maptest.c maptest.h +maptest: maptest.o + $(CC_LINK) -o maptest maptest.o + +##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 errmap.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@ + diff --git a/krb5-1-7/src/lib/gssapi/generic/deps b/krb5-1-7/src/lib/gssapi/generic/deps new file mode 100644 index 000000000..652f80871 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/deps @@ -0,0 +1,73 @@ +# +# Generated makefile dependencies follow. +# +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/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h disp_com_err_status.c \ + gssapiP_generic.h gssapi_err_generic.h gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h disp_major_status.c gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.h gssapi_generic.c gssapi_generic.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.h gssapi_generic.h oid_ops.c +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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.h gssapi_generic.h util_buffer.c +util_buffer_set.so util_buffer_set.po $(OUTPRE)util_buffer_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.h gssapi_generic.h util_buffer_set.c +util_errmap.so util_errmap.po $(OUTPRE)util_errmap.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h errmap.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_errmap.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h gssapiP_generic.h gssapi_err_generic.h \ + gssapi_ext.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-7/src/lib/gssapi/generic/disp_com_err_status.c b/krb5-1-7/src/lib/gssapi/generic/disp_com_err_status.c new file mode 100644 index 000000000..d7a2e1d85 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/disp_com_err_status.c @@ -0,0 +1,64 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 "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; + + 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-7/src/lib/gssapi/generic/disp_major_status.c b/krb5-1-7/src/lib/gssapi/generic/disp_major_status.c new file mode 100644 index 000000000..f9ff28147 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/disp_major_status.c @@ -0,0 +1,310 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#include + +/* + * $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 (asprintf(&str, unknown_error, kind, value) < 0) + return(0); + + 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< 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)< +# 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 pack(push,2) +#endif + +#if defined(_MSDOS) || defined(_WIN32) +#include +#endif + +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +/* + * First, include stddef.h to get size_t defined. + */ +#include + +/* + * POSIX says that sys/types.h is where size_t is defined. + */ +#include + +/* + * $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 +#define GSS_C_DELEG_POLICY_FLAG 32768 + +/* + * 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_NETBIOS 20 +#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 pack(pop) +#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-7/src/lib/gssapi/generic/gssapiP_generic.h b/krb5-1-7/src/lib/gssapi/generic/gssapiP_generic.h new file mode 100644 index 000000000..b684055c4 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/gssapiP_generic.h @@ -0,0 +1,297 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#endif +#endif + +#include "k5-thread.h" + +#include "gssapi_generic.h" +#include "gssapi_ext.h" +#include "gssapi_err_generic.h" +#include + +#include "k5-platform.h" +#include "k5-buf.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) \ + if (bigend) store_32_be(num, ptr); else store_32_le(num, ptr); \ + (ptr) += 4; + +#define TWRITE_INT16(ptr, num, bigend) \ + if (bigend) store_16_be((num)>>16, ptr); else store_16_le(num, ptr); \ + (ptr) += 2; + +#define TREAD_INT(ptr, num, bigend) \ + (num) = ((bigend) ? load_32_be(ptr) : load_32_le(ptr)); \ + (ptr) += 4; + +#define TREAD_INT16(ptr, num, bigend) \ + (num) = ((bigend) ? (load_16_be(ptr) << 16) : load_16_le(ptr)); \ + (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); + +/* flags for g_verify_token_header() */ +#define G_VFY_TOKEN_HDR_WRAPPER_REQUIRED 0x01 +#define G_VFY_TOKEN_HDR_IGNORE_SEQ_SIZE 0x02 + +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 flags); + +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 */ + +OM_uint32 +generic_gss_oid_compose( + OM_uint32 *, /* minor_status */ + const char *, /* prefix */ + size_t, /* prefix_len */ + int, /* suffix */ + gss_OID_desc *); /* oid */ + +OM_uint32 +generic_gss_oid_decompose( + OM_uint32 *, /* minor_status */ + const char *, /*prefix */ + size_t, /* prefix_len */ + gss_OID_desc *, /* oid */ + int *); /* suffix */ + +int gssint_mecherrmap_init(void); +void gssint_mecherrmap_destroy(void); +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc *oid); +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor); +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode); + +OM_uint32 generic_gss_create_empty_buffer_set +(OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_add_buffer_set_member +(OM_uint32 * /*minor_status*/, + const gss_buffer_t /*member_buffer*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_release_buffer_set +(OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_copy_oid_set +(OM_uint32 *, /* minor_status */ + const gss_OID_set_desc *, /* const oidset*/ + gss_OID_set * /*new_oidset*/); + +#endif /* _GSSAPIP_GENERIC_H_ */ diff --git a/krb5-1-7/src/lib/gssapi/generic/gssapi_err_generic.et b/krb5-1-7/src/lib/gssapi/generic/gssapi_err_generic.et new file mode 100644 index 000000000..3e976e3db --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/generic/gssapi_ext.h b/krb5-1-7/src/lib/gssapi/generic/gssapi_ext.h new file mode 100644 index 000000000..40f5ab809 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/gssapi_ext.h @@ -0,0 +1,261 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 GSSAPI_EXT_H_ +#define GSSAPI_EXT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if 0 +/* + * Solaris extensions + */ +int KRB5_CALLCONV gssd_pname_to_uid + (char *, + gss_OID, + gss_OID, + uid_t *); + +int KRB5_CALLCONV __gss_userok + (const gss_name_t /*name*/, + const char * /*username*/); +#endif + +/* + * GGF extensions + */ +typedef struct gss_buffer_set_desc_struct { + size_t count; + gss_buffer_desc *elements; +} gss_buffer_set_desc, *gss_buffer_set_t; + +#define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t) 0) + +OM_uint32 KRB5_CALLCONV gss_create_empty_buffer_set + (OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_add_buffer_set_member + (OM_uint32 * /*minor_status*/, + const gss_buffer_t /*member_buffer*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_release_buffer_set + (OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_inquire_sec_context_by_oid + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t * /*data_set*/); + +OM_uint32 KRB5_CALLCONV gss_inquire_cred_by_oid + (OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t * /*data_set*/); + +OM_uint32 KRB5_CALLCONV gss_set_sec_context_option + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*cred_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +/* XXX do these really belong in this header? */ +OM_uint32 KRB5_CALLCONV gssspi_set_cred_option + (OM_uint32 * /*minor_status*/, + gss_cred_id_t /*cred*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +OM_uint32 KRB5_CALLCONV gssspi_mech_invoke + (OM_uint32 * /*minor_status*/, + const gss_OID /*desired_mech*/, + const gss_OID /*desired_object*/, + gss_buffer_t /*value*/); + +/* + * AEAD extensions + */ + +OM_uint32 KRB5_CALLCONV gss_wrap_aead + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + gss_buffer_t /*input_assoc_buffer*/, + gss_buffer_t /*input_payload_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/); + +OM_uint32 KRB5_CALLCONV gss_unwrap_aead + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*input_assoc_buffer*/, + gss_buffer_t /*output_payload_buffer*/, + int * /*conf_state*/, + gss_qop_t * /*qop_state*/); + +/* + * SSPI extensions + */ +#define GSS_C_DCE_STYLE 0x1000 +#define GSS_C_IDENTIFY_FLAG 0x2000 +#define GSS_C_EXTENDED_ERROR_FLAG 0x4000 + +/* + * Returns a buffer set with the first member containing the + * session key for SSPI compatibility. The optional second + * member contains an OID identifying the session key type. + */ +GSS_DLLIMP extern gss_OID GSS_C_INQ_SSPI_SESSION_KEY; + +OM_uint32 KRB5_CALLCONV gss_complete_auth_token + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer); + +typedef struct gss_iov_buffer_desc_struct { + OM_uint32 type; + gss_buffer_desc buffer; +} gss_iov_buffer_desc, *gss_iov_buffer_t; + +#define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0) + +#define GSS_IOV_BUFFER_TYPE_EMPTY 0 +#define GSS_IOV_BUFFER_TYPE_DATA 1 /* Packet data */ +#define GSS_IOV_BUFFER_TYPE_HEADER 2 /* Mechanism header */ +#define GSS_IOV_BUFFER_TYPE_MECH_PARAMS 3 /* Mechanism specific parameters */ +#define GSS_IOV_BUFFER_TYPE_TRAILER 7 /* Mechanism trailer */ +#define GSS_IOV_BUFFER_TYPE_PADDING 9 /* Padding */ +#define GSS_IOV_BUFFER_TYPE_STREAM 10 /* Complete wrap token */ +#define GSS_IOV_BUFFER_TYPE_SIGN_ONLY 11 /* Sign only packet data */ + +#define GSS_IOV_BUFFER_FLAG_MASK 0xFFFF0000 +#define GSS_IOV_BUFFER_FLAG_ALLOCATE 0x00010000 /* indicates GSS should allocate */ +#define GSS_IOV_BUFFER_FLAG_ALLOCATED 0x00020000 /* indicates caller should free */ + +#define GSS_IOV_BUFFER_TYPE(_type) ((_type) & ~(GSS_IOV_BUFFER_FLAG_MASK)) +#define GSS_IOV_BUFFER_FLAGS(_type) ((_type) & GSS_IOV_BUFFER_FLAG_MASK) + +/* + * Sign and optionally encrypt a sequence of buffers. The buffers + * shall be ordered HEADER | DATA | PADDING | TRAILER. Suitable + * space for the header, padding and trailer should be provided + * by calling gss_wrap_iov_length(), or the ALLOCATE flag should + * be set on those buffers. + * + * Encryption is in-place. SIGN_ONLY buffers are untouched. Only + * a single PADDING buffer should be provided. The order of the + * buffers in memory does not matter. Buffers in the IOV should + * be arranged in the order above, and in the case of multiple + * DATA buffers the sender and receiver should agree on the + * order. + * + * With GSS_C_DCE_STYLE it is acceptable to not provide PADDING + * and TRAILER, but the caller must guarantee the plaintext data + * being encrypted is correctly padded, otherwise an error will + * be returned. + * + * While applications that have knowledge of the underlying + * cryptosystem may request a specific configuration of data + * buffers, the only generally supported configurations are: + * + * HEADER | DATA | PADDING | TRAILER + * + * which will emit GSS_Wrap() compatible tokens, and: + * + * HEADER | SIGN_ONLY | DATA | PADDING | TRAILER + * + * for AEAD. + * + * The typical (special cased) usage for DCE is as follows: + * + * SIGN_ONLY_1 | DATA | SIGN_ONLY_2 | HEADER + */ +OM_uint32 KRB5_CALLCONV gss_wrap_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Verify and optionally decrypt a sequence of buffers. To process + * a GSS-API message without separate buffer, pass STREAM | DATA. + * Upon return DATA will contain the decrypted or integrity + * protected message. Only a single DATA buffer may be provided + * with this usage. DATA by default will point into STREAM, but if + * the ALLOCATE flag is set a copy will be returned. + * + * Otherwise, decryption is in-place. SIGN_ONLY buffers are + * untouched. + */ +OM_uint32 KRB5_CALLCONV gss_unwrap_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Query HEADER, PADDING and TRAILER buffer lengths. DATA buffers + * should be provided so the correct padding length can be determined. + */ +OM_uint32 KRB5_CALLCONV gss_wrap_iov_length +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Release buffers that have the ALLOCATED flag set. + */ +OM_uint32 KRB5_CALLCONV gss_release_iov_buffer +( + OM_uint32 *, /* minor_status */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +#ifdef __cplusplus +} +#endif + +#endif /* GSSAPI_EXT_H_ */ diff --git a/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.c b/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.c new file mode 100644 index 000000000..14724619a --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.c @@ -0,0 +1,155 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + */ + + /* GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"}, +}; + +/* 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; + +GSS_DLLIMP gss_OID GSS_C_INQ_SSPI_SESSION_KEY = oids+7; + diff --git a/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.h b/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.h new file mode 100644 index 000000000..c5399dc72 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/gssapi_generic.h @@ -0,0 +1,59 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 + +#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 + +#define GSS_EMPTY_BUFFER(buf) ((buf) == NULL ||\ + (buf)->value == NULL || (buf)->length == 0) + +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-7/src/lib/gssapi/generic/maptest.c b/krb5-1-7/src/lib/gssapi/generic/maptest.c new file mode 100644 index 000000000..ce594218d --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/maptest.c @@ -0,0 +1,68 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +#include +#include +#include + +typedef struct { int a, b; } elt; +static int eltcp(elt *dest, elt src) +{ + *dest = src; + return 0; +} +static int eltcmp(elt left, elt right) +{ + if (left.a < right.a) + return -1; + if (left.a > right.a) + return 1; + if (left.b < right.b) + return -1; + if (left.b > right.b) + return 1; + return 0; +} +static void eltprt(elt v, FILE *f) +{ + fprintf(f, "{%d,%d}", v.a, v.b); +} +static int intcmp(int left, int right) +{ + if (left < right) + return -1; + if (left > right) + return 1; + return 0; +} +static void intprt(int v, FILE *f) +{ + fprintf(f, "%d", v); +} + +#include "maptest.h" + +foo foo1; + +int main () +{ + elt v1 = { 1, 2 }, v2 = { 3, 4 }; + const elt *vp; + const int *ip; + + assert(0 == foo_init(&foo1)); + vp = foo_findleft(&foo1, 47); + assert(vp == NULL); + assert(0 == foo_add(&foo1, 47, v1)); + vp = foo_findleft(&foo1, 47); + assert(vp != NULL); + assert(0 == eltcmp(*vp, v1)); + vp = foo_findleft(&foo1, 3); + assert(vp == NULL); + assert(0 == foo_add(&foo1, 93, v2)); + ip = foo_findright(&foo1, v1); + assert(ip != NULL); + assert(*ip == 47); + printf("Map content: "); + foo_printmap(&foo1, stdout); + printf("\n"); + return 0; +} diff --git a/krb5-1-7/src/lib/gssapi/generic/oid_ops.c b/krb5-1-7/src/lib/gssapi/generic/oid_ops.c new file mode 100644 index 000000000..8390e7ba0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/oid_ops.c @@ -0,0 +1,569 @@ +/* #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 "gssapiP_generic.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include + +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; icount; 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; +{ + OM_uint32 number; + OM_uint32 i; + unsigned char *cp; + char *bp; + struct k5buf buf; + + 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 */ + + cp = (unsigned char *) oid->elements; + number = (unsigned long) cp[0]; + krb5int_buf_init_dynamic(&buf); + krb5int_buf_add_fmt(&buf, "{ %lu %lu ", (unsigned long)number/40, + (unsigned long)number%40); + number = 0; + cp = (unsigned char *) oid->elements; + for (i=1; ilength; i++) { + number = (number << 7) | (cp[i] & 0x7f); + if ((cp[i] & 0x80) == 0) { + krb5int_buf_add_fmt(&buf, "%lu ", (unsigned long)number); + number = 0; + } + } + krb5int_buf_add(&buf, "}"); + bp = krb5int_buf_data(&buf); + if (bp == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + oid_str->length = krb5int_buf_len(&buf)+1; + oid_str->value = (void *) bp; + return(GSS_S_COMPLETE); +} + +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 i; + 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 == '.')) + 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; + i = -1; + while (numbuf) { + op[i] = (unsigned char) numbuf & 0x7f; + if (i != -1) + op[i] |= 0x80; + i--; + 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); +} + +/* Compose an OID of a prefix and an integer suffix */ +OM_uint32 +generic_gss_oid_compose( + OM_uint32 *minor_status, + const char *prefix, + size_t prefix_len, + int suffix, + gss_OID_desc *oid) +{ + int osuffix, i; + size_t nbytes; + unsigned char *op; + + if (oid == GSS_C_NO_OID) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + if (oid->length < prefix_len) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + memcpy(oid->elements, prefix, prefix_len); + + nbytes = 0; + osuffix = suffix; + while (suffix) { + nbytes++; + suffix >>= 7; + } + suffix = osuffix; + + if (oid->length < prefix_len + nbytes) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + op = (unsigned char *) oid->elements + prefix_len + nbytes; + i = -1; + while (suffix) { + op[i] = (unsigned char)suffix & 0x7f; + if (i != -1) + op[i] |= 0x80; + i--; + suffix >>= 7; + } + + oid->length = prefix_len + nbytes; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +generic_gss_oid_decompose( + OM_uint32 *minor_status, + const char *prefix, + size_t prefix_len, + gss_OID_desc *oid, + int *suffix) +{ + size_t i, slen; + unsigned char *op; + + if (oid->length < prefix_len || + memcmp(oid->elements, prefix, prefix_len) != 0) { + return GSS_S_BAD_MECH; + } + + op = (unsigned char *) oid->elements + prefix_len; + + *suffix = 0; + + slen = oid->length - prefix_len; + + for (i = 0; i < slen; i++) { + *suffix = (*suffix << 7) | (op[i] & 0x7f); + if (i + 1 != slen && (op[i] & 0x80) == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + return GSS_S_COMPLETE; +} + +/* + * 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 +generic_gss_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 i; + + 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 (i = 0; i < copy->count; i++) { + gss_OID_desc *out = ©->elements[i]; + gss_OID_desc *in = &oidset->elements[i]; + + 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-7/src/lib/gssapi/generic/rel_buffer.c b/krb5-1-7/src/lib/gssapi/generic/rel_buffer.c new file mode 100644 index 000000000..8b35e8037 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/rel_buffer.c @@ -0,0 +1,57 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 +generic_gss_release_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-7/src/lib/gssapi/generic/rel_oid_set.c b/krb5-1-7/src/lib/gssapi/generic/rel_oid_set.c new file mode 100644 index 000000000..137a513a0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/rel_oid_set.c @@ -0,0 +1,61 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 +generic_gss_release_oid_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-7/src/lib/gssapi/generic/util_buffer.c b/krb5-1-7/src/lib/gssapi/generic/util_buffer.c new file mode 100644 index 000000000..b707d15fb --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_buffer.c @@ -0,0 +1,45 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 + +/* 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(const char *str, gss_buffer_t buffer) +{ + buffer->length = strlen(str); + + if ((buffer->value = strdup(str)) == NULL) { + buffer->length = 0; + return(0); + } + + return(1); +} diff --git a/krb5-1-7/src/lib/gssapi/generic/util_buffer_set.c b/krb5-1-7/src/lib/gssapi/generic/util_buffer_set.c new file mode 100644 index 000000000..edb61b80f --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_buffer_set.c @@ -0,0 +1,126 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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_generic.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 generic_gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + + set = (gss_buffer_set_desc *) malloc(sizeof(*set)); + if (set == GSS_C_NO_BUFFER_SET) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + set->count = 0; + set->elements = NULL; + + *buffer_set = set; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 generic_gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + gss_buffer_t p; + OM_uint32 ret; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + ret = generic_gss_create_empty_buffer_set(minor_status, + buffer_set); + if (ret) { + return ret; + } + } + + set = *buffer_set; + set->elements = (gss_buffer_desc *)realloc(set->elements, + (set->count + 1) * + sizeof(gss_buffer_desc)); + if (set->elements == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = &set->elements[set->count]; + + p->value = malloc(member_buffer->length); + if (p->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(p->value, member_buffer->value, member_buffer->length); + p->length = member_buffer->length; + + set->count++; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 generic_gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + int i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + return GSS_S_COMPLETE; + } + + for (i = 0; i < (*buffer_set)->count; i++) { + generic_gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + } + + if ((*buffer_set)->elements != NULL) { + free((*buffer_set)->elements); + (*buffer_set)->elements = NULL; + } + + (*buffer_set)->count = 0; + + free(*buffer_set); + *buffer_set = GSS_C_NO_BUFFER_SET; + + return GSS_S_COMPLETE; +} + diff --git a/krb5-1-7/src/lib/gssapi/generic/util_canonhost.c b/krb5-1-7/src/lib/gssapi/generic/util_canonhost.c new file mode 100644 index 000000000..6e953186d --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_canonhost.c @@ -0,0 +1,69 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#endif +#include +#include + +char * +g_canonicalize_host(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 *) strdup(hent->h_name)) == NULL) + return(NULL); + + for (str = canon; *str; str++) + if (isupper(*str)) *str = tolower(*str); + + return(canon); +} diff --git a/krb5-1-7/src/lib/gssapi/generic/util_errmap.c b/krb5-1-7/src/lib/gssapi/generic/util_errmap.c new file mode 100644 index 000000000..2634e667b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_errmap.c @@ -0,0 +1,276 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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_generic.h" +#include +#ifndef _WIN32 +#include +#endif + +/* The mapping table is 0-based, but let's export codes that are + 1-based, keeping 0 for errors or unknown errors. + + The elements in the mapping table currently have separate copies of + each OID stored. This is a bit wasteful, but we are assuming the + table isn't likely to grow very large. */ + +struct mecherror { + gss_OID_desc mech; + OM_uint32 code; +}; + +static inline int +cmp_OM_uint32(OM_uint32 m1, OM_uint32 m2) +{ + if (m1 < m2) + return -1; + else if (m1 > m2) + return 1; + else + return 0; +} + +static inline int +mecherror_cmp(struct mecherror m1, struct mecherror m2) +{ + if (m1.code < m2.code) + return -1; + if (m1.code > m2.code) + return 1; + if (m1.mech.length < m2.mech.length) + return -1; + if (m1.mech.length > m2.mech.length) + return 1; + if (m1.mech.length == 0) + return 0; + return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length); +} + +static void +print_OM_uint32 (OM_uint32 value, FILE *f) +{ + fprintf(f, "%lu", (unsigned long) value); +} + +static inline int +mecherror_copy(struct mecherror *dest, struct mecherror src) +{ + *dest = src; + dest->mech.elements = malloc(src.mech.length); + if (dest->mech.elements == NULL) { + if (src.mech.length) + return ENOMEM; + else + return 0; + } + memcpy(dest->mech.elements, src.mech.elements, src.mech.length); + return 0; +} + +static void +mecherror_print(struct mecherror value, FILE *f) +{ + OM_uint32 minor; + gss_buffer_desc str; + static const struct { + const char *oidstr, *name; + } mechnames[] = { + { "{ 1 2 840 113554 1 2 2 }", "krb5-new" }, + { "{ 1 3 5 1 5 2 }", "krb5-old" }, + { "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" }, + { "{ 1 3 6 1 5 5 2 }", "spnego" }, + }; + unsigned int i; + + fprintf(f, "%lu@", (unsigned long) value.code); + + if (value.mech.length == 0) { + fprintf(f, "(com_err)"); + return; + } + fprintf(f, "%p=", value.mech.elements); + if (generic_gss_oid_to_str(&minor, &value.mech, &str)) { + fprintf(f, "(error in conversion)"); + return; + } + /* Note: generic_gss_oid_to_str returns a null-terminated string. */ + for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) { + if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) { + fprintf(f, "%s", mechnames[i].name); + break; + } + } + if (i == sizeof(mechnames)/sizeof(mechnames[0])) + fprintf(f, "%s", (char *) str.value); + generic_gss_release_buffer(&minor, &str); +} + +#include "errmap.h" +#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */ + +static mecherrmap m; +static k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static OM_uint32 next_fake = 100000; + +int gssint_mecherrmap_init(void) +{ + int err; + + err = mecherrmap_init(&m); + if (err) + return err; + err = k5_mutex_finish_init(&mutex); + if (err) { + mecherrmap_destroy(&m); + return err; + } + + return 0; +} + +/* Currently the enumeration template doesn't handle freeing + element storage when destroying the collection. */ +static int free_one(OM_uint32 i, struct mecherror value, void *p) +{ + if (value.mech.length && value.mech.elements) + free(value.mech.elements); + return 0; +} + +void gssint_mecherrmap_destroy(void) +{ + mecherrmap_foreach(&m, free_one, NULL); + mecherrmap_destroy(&m); + k5_mutex_destroy(&mutex); +} + +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid) +{ + const struct mecherror *mep; + struct mecherror me, me_copy; + const OM_uint32 *p; + int err; + OM_uint32 new_status; + +#ifdef DEBUG + FILE *f; + f = fopen("/dev/pts/9", "w+"); + if (f == NULL) + f = stderr; +#endif + + me.code = minor; + me.mech = *oid; + err = k5_mutex_lock(&mutex); + if (err) { +#ifdef DEBUG + if (f != stderr) fclose(f); +#endif + return 0; + } + + /* Is this status+oid already mapped? */ + p = mecherrmap_findright(&m, me); + if (p != NULL) { + k5_mutex_unlock(&mutex); +#ifdef DEBUG + fprintf(f, "%s: found ", __func__); + mecherror_print(me, f); + fprintf(f, " in map as %lu\n", (unsigned long) *p); + if (f != stderr) fclose(f); +#endif + return *p; + } + /* Is this status code already mapped to something else + mech-specific? */ + mep = mecherrmap_findleft(&m, minor); + if (mep == NULL) { + /* Map it to itself plus this mech-oid. */ + new_status = minor; + } else { + /* Already assigned. Pick a fake new value and map it. */ + /* There's a theoretical infinite loop risk here, if we fill + in 2**32 values. Also, returning 0 has a special + meaning. */ + do { + next_fake++; + new_status = next_fake; + if (new_status == 0) + /* ??? */; + } while (mecherrmap_findleft(&m, new_status) != NULL); + } + err = mecherror_copy(&me_copy, me); + if (err) { + k5_mutex_unlock(&mutex); + return err; + } + err = mecherrmap_add(&m, new_status, me_copy); + k5_mutex_unlock(&mutex); + if (err) { + if (me_copy.mech.length) + free(me_copy.mech.elements); + } +#ifdef DEBUG + fprintf(f, "%s: mapping ", __func__); + mecherror_print(me, f); + fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err); + mecherrmap_printmap(&m, f); + fprintf(f, "\n"); + if (f != stderr) fclose(f); +#endif + if (err) + return 0; + else + return new_status; +} + +static gss_OID_desc no_oid = { 0, 0 }; +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode) +{ + return gssint_mecherrmap_map(errcode, &no_oid); +} + +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor) +{ + const struct mecherror *p; + int err; + + if (minor == 0) { + return EINVAL; + } + err = k5_mutex_lock(&mutex); + if (err) + return err; + p = mecherrmap_findleft(&m, minor); + k5_mutex_unlock(&mutex); + if (!p) { + return EINVAL; + } + *mech_oid = p->mech; + *mech_minor = p->code; + return 0; +} diff --git a/krb5-1-7/src/lib/gssapi/generic/util_localhost.c b/krb5-1-7/src/lib/gssapi/generic/util_localhost.c new file mode 100644 index 000000000..85e098047 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_localhost.c @@ -0,0 +1,49 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 + +#include "gssapiP_generic.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +char * +g_local_host_name(void) +{ + char buf[MAXHOSTNAMELEN+1], *ptr; + + if (gethostname(buf, sizeof(buf)) < 0) + return 0; + + buf[sizeof(buf)-1] = '\0'; + + return strdup(buf); +} diff --git a/krb5-1-7/src/lib/gssapi/generic/util_ordering.c b/krb5-1-7/src/lib/gssapi/generic/util_ordering.c new file mode 100644 index 000000000..274790e4e --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_ordering.c @@ -0,0 +1,252 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 + +#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; istart+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-7/src/lib/gssapi/generic/util_set.c b/krb5-1-7/src/lib/gssapi/generic/util_set.c new file mode 100644 index 000000000..d437f1ea7 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_set.c @@ -0,0 +1,106 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/gssapi/generic/util_token.c b/krb5-1-7/src/lib/gssapi/generic/util_token.c new file mode 100644 index 000000000..b59778836 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_token.c @@ -0,0 +1,230 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#endif +#include + +/* + * $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) + * possible multiple bytes, need to parse/generate + * 0x06 tag for OBJECT IDENTIFIER + * compile-time constant string (assume 1 byte) + * compile-time constant string + * 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(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(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(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(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( + 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( + const gss_OID_desc * mech, + unsigned int *body_size, + unsigned char **buf_in, + int tok_type, + unsigned int toksize_in, + int flags) +{ + 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 (flags & G_VFY_TOKEN_HDR_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 ((flags & G_VFY_TOKEN_HDR_IGNORE_SEQ_SIZE) == 0 && + 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-7/src/lib/gssapi/generic/util_validate.c b/krb5-1-7/src/lib/gssapi/generic/util_validate.c new file mode 100644 index 000000000..00dac321c --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/util_validate.c @@ -0,0 +1,314 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include + +#ifdef HAVE_BSD_DB +#include +#include + +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 = 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 = 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-7/src/lib/gssapi/generic/utl_nohash_validate.c b/krb5-1-7/src/lib/gssapi/generic/utl_nohash_validate.c new file mode 100644 index 000000000..d221b3722 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/generic/utl_nohash_validate.c @@ -0,0 +1,121 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#endif +#ifdef HAVE_LIMITS_H +#include +#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-7/src/lib/gssapi/krb5/3des.txt b/krb5-1-7/src/lib/gssapi/krb5/3des.txt new file mode 100644 index 000000000..64ca1ac49 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/krb5/Makefile.in b/krb5-1-7/src/lib/gssapi/krb5/Makefile.in new file mode 100644 index 000000000..530d527c2 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/Makefile.in @@ -0,0 +1,273 @@ +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=-D_GSS_STATIC_LINK=1 + +#PROG_LIBPATH=-L$(TOPLIBD) +#PROG_RPATH=$(KRB5_LIBDIR) +#MODULE_INSTALL_DIR = $(GSS_MODULE_DIR) +#LIBBASE=mech_krb5 +#LIBMAJOR=0 +#LIBMINOR=0 +#SO_EXT=.so +#LIBINITFUNC=gss_krb5int_init +#LIBFINIFUNC=gss_krb5int_fini +#STOBJLISTS=../generic/OBJS.ST OBJS.ST +#SUBDIROBJLISTS=../generic/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/krb5 + +##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)/k5sealiov.c \ + $(srcdir)/k5sealv3.c \ + $(srcdir)/k5sealv3iov.c \ + $(srcdir)/k5unseal.c \ + $(srcdir)/k5unsealiov.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 + + +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)k5sealiov.$(OBJEXT) \ + $(OUTPRE)k5sealv3.$(OBJEXT) \ + $(OUTPRE)k5sealv3iov.$(OBJEXT) \ + $(OUTPRE)k5unseal.$(OBJEXT) \ + $(OUTPRE)k5unsealiov.$(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 \ + k5sealiov.o \ + k5sealv3.o \ + k5sealv3iov.o \ + k5unseal.o \ + k5unsealiov.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 + +error_map.h: $(SRCTOP)/util/gen-map.pl $(SRCTOP)/util/ktemplate.pm Makefile + $(PERL) -I$(SRCTOP)/util $(SRCTOP)/util/gen-map.pl -oerror_map.new \ + NAME=gsserrmap \ + KEY=OM_uint32 \ + VALUE="char *" \ + COMPARE=compare_OM_uint32 \ + FREEVALUE=free_string + $(MV) error_map.new error_map.h + +clean-unix:: + $(RM) $(BUILDTOP)/include/gssapi/gssapi_krb5.h + -$(RM) gssapi_krb5.h error_map.h + +clean-unix:: clean-libobjs + $(RM) $(ETHDRS) $(ETSRCS) + +clean-windows:: + $(RM) $(EHDRDIR)\gssapi_krb5.h + $(RM) error_map.h + -if exist $(EHDRDIR)\nul rmdir $(EHDRDIR) + + +generate-files-mac: gssapi_krb5.h error_map.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@ + diff --git a/krb5-1-7/src/lib/gssapi/krb5/accept_sec_context.c b/krb5-1-7/src/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 000000000..dd17c044b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,1232 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2004, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ +/* + * Copyright (c) 2006-2008, 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" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + + +#ifdef CFX_EXERCISE +#define CFX_ACCEPTOR_SUBKEY (time(0) & 1) +#else +#define CFX_ACCEPTOR_SUBKEY 1 +#endif + +#ifndef LEAN_CLIENT + +/* 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; +} + + +/* + * Performs third leg of DCE authentication + */ +static OM_uint32 +kg_accept_dce(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_error_code code; + krb5_gss_ctx_id_rec *ctx = 0; + krb5_timestamp now; + krb5_principal name = NULL; + krb5_ui_4 nonce = 0; + krb5_data ap_rep; + OM_uint32 major_status = GSS_S_FAILURE; + + output_token->length = 0; + output_token->value = NULL; + + 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; + + ctx = (krb5_gss_ctx_id_rec *)*context_handle; + + code = krb5_timeofday(ctx->k5_context, &now); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + if (ctx->krb_times.endtime < now) { + code = 0; + major_status = GSS_S_CREDENTIALS_EXPIRED; + goto fail; + } + + ap_rep.data = input_token->value; + ap_rep.length = input_token->length; + + code = krb5_rd_rep_dce(ctx->k5_context, + ctx->auth_context, + &ap_rep, + &nonce); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + ctx->established = 1; + + if (src_name) { + if ((code = krb5_copy_principal(ctx->k5_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; + } + *src_name = (gss_name_t) name; + } + + if (mech_type) + *mech_type = ctx->mech_used; + + if (time_rec) + *time_rec = ctx->krb_times.endtime - now; + + if (ret_flags) + *ret_flags = ctx->gss_flags; + + /* XXX no support for delegated credentials yet */ + + *minor_status = 0; + + return GSS_S_COMPLETE; + + fail: + /* real failure code follows */ + + (void) krb5_gss_delete_sec_context(minor_status, (gss_ctx_id_t *) &ctx, + NULL); + *context_handle = GSS_C_NO_CONTEXT; + *minor_status = code; + + return major_status; +} + +static OM_uint32 +kg_accept_krb5(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; + OM_uint32 tmp; + size_t md5len; + int bigend; + krb5_gss_cred_id_t cred = 0; + krb5_data ap_rep, ap_req; + unsigned 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 = NULL; + 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; + OM_uint32 tmp_minor_status; + 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; + int no_encap = 0; + krb5_flags ap_req_options = 0; + krb5_enctype negotiated_etype; + + 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; + + /* 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 if (code == G_BAD_TOK_HEADER) { + /* DCE style not encapsulated */ + ap_req.length = input_token->length; + ap_req.data = input_token->value; + mech_used = gss_mech_krb5; + no_encap = 1; + } 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; + save_error_info((OM_uint32)code, context); + 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, &ap_req_options, &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 + + if (authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) { + /* Samba does not send 0x8003 GSS-API checksums */ + krb5_boolean valid; + krb5_keyblock *subkey; + krb5_data zero; + + code = krb5_auth_con_getkey(context, auth_context, &subkey); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + + zero.length = 0; + zero.data = ""; + + code = krb5_c_verify_checksum(context, + subkey, + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, + &zero, + authdat->checksum, + &valid); + if (code || !valid) { + major_status = GSS_S_BAD_SIG; + krb5_free_keyblock(context, subkey); + goto fail; + } + + gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + bigend = 0; + decode_req_message = 0; + + krb5_free_keyblock(context, subkey); + } else { + /* 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 + } + } + + /* only DCE_STYLE clients are allowed to send raw AP-REQs */ + if (no_encap != ((gss_flags & GSS_C_DCE_STYLE) != 0)) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto fail; + } + + /* 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 | + GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | + GSS_C_EXTENDED_ERROR_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; + } + + /* XXX move this into gss_name_t */ + if ( (code = krb5_merge_authdata(context, + ticket->enc_part2->authorization_data, + authdat->authorization_data, + &ctx->authdata))) { + 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->enc = NULL; + ctx->seq = NULL; + ctx->have_acceptor_subkey = 0; + /* DCE_STYLE implies acceptor_subkey */ + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + code = kg_setup_keys(context, ctx, ctx->subkey, &ctx->cksumtype); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + ctx->krb_times = ticket->enc_part2->times; /* struct copy */ + ctx->krb_flags = ticket->enc_part2->flags; + + krb5_free_ticket(context, ticket); /* Done with ticket */ + + { + krb5_int32 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->krb_times.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); + + /* DCE_STYLE implies mutual authentication */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) + ctx->gss_flags |= GSS_C_MUTUAL_FLAG; + + /* 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_int32 seq_temp; + int cfx_generate_subkey; + + /* + * Do not generate a subkey per RFC 4537 unless we are upgrading to CFX, + * because pre-CFX tokens do not indicate which key to use. (Note that + * DCE_STYLE implies that we will use a subkey.) + */ + if (ctx->proto == 0 && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && + (ap_req_options & AP_OPTS_USE_SUBKEY)) { + code = (*kaccess.krb5_auth_con_get_subkey_enctype) (context, + auth_context, + &negotiated_etype); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + switch (negotiated_etype) { + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + ap_req_options &= ~(AP_OPTS_USE_SUBKEY); + break; + } + } + + if (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) || + (ap_req_options & AP_OPTS_USE_SUBKEY)) + 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; + } + ctx->have_acceptor_subkey = 1; + + code = kg_setup_keys(context, ctx, ctx->acceptor_subkey, + &ctx->acceptor_subkey_cksumtype); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + /* the reply token hasn't been sent yet, but that's ok. */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + assert(ctx->have_acceptor_subkey); + + /* in order to force acceptor subkey to be used, don't set PROT_READY */ + + /* Raw AP-REP is returned */ + output_token->length = ap_rep.length; + output_token->value = ap_rep.data; + ap_rep.data = NULL; /* don't double free */ + + ctx->established = 0; + + *context_handle = (gss_ctx_id_t)ctx; + *minor_status = 0; + major_status = GSS_S_CONTINUE_NEEDED; + + /* Only last leg should set return arguments */ + goto fail; + } else + 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->krb_times.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 (major_status == GSS_S_COMPLETE || + (major_status == GSS_S_CONTINUE_NEEDED && code != KRB5KRB_AP_ERR_MSG_TYPE)) { + ctx->k5_context = context; + context = NULL; + goto done; + } + + /* from here on is the real "fail" code */ + + if (ctx) + (void) krb5_gss_delete_sec_context(&tmp_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)) + goto done; + + 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) + goto done; + + 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) + goto done; + + 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; + } + +done: + if (!verifier_cred_handle && cred_handle) { + krb5_gss_release_cred(&tmp_minor_status, &cred_handle); + } + if (context) { + if (major_status && *minor_status) + save_error_info(*minor_status, context); + krb5_free_context(context); + } + return (major_status); +} +#endif /* LEAN_CLIENT */ + +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_gss_ctx_id_rec *ctx = (krb5_gss_ctx_id_rec *)*context_handle; + + /* + * 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 (ctx != NULL) { + if (ctx->established == 0 && (ctx->gss_flags & GSS_C_DCE_STYLE)) { + return kg_accept_dce(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); + } else { + *minor_status = EINVAL; + save_error_string(EINVAL, "accept_sec_context called with existing context handle"); + return GSS_S_FAILURE; + } + } + + return kg_accept_krb5(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); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/acquire_cred.c b/krb5-1-7/src/lib/gssapi/krb5/acquire_cred.c new file mode 100644 index 000000000..48471b4f4 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/acquire_cred.c @@ -0,0 +1,761 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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_STRING_H +#include +#else +#include +#endif + +#if defined(USE_KIM) +#include +#include "kim_library_private.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 + +#ifndef LEAN_CLIENT +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 +gss_krb5int_register_acceptor_identity(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + char *new, *old; + int err; + + err = gss_krb5int_initialize_library(); + if (err != 0) + return GSS_S_FAILURE; + + if (value->value == NULL) + return GSS_S_FAILURE; + + new = strdup((char *)value->value); + if (new == NULL) + return GSS_S_FAILURE; + + 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 = gss_krb5int_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) { + char *errstr = (char *)krb5_get_error_message(context, code); + krb5_set_error_message(context, KG_KEYTAB_NOMATCH, "%s", errstr); + krb5_free_error_message(context, errstr); + *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); +} +#endif /* LEAN_CLIENT */ + +/* 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_KIM) || defined(USE_LEASH) + if (desired_name && !caller_provided_ccache_name) { +#if defined(USE_KIM) + kim_error err = KIM_NO_ERROR; + kim_ccache kimccache = NULL; + kim_identity identity = NULL; + kim_credential_state state; + krb5_principal desired_princ = (krb5_principal) desired_name; + + err = kim_identity_create_from_krb5_principal (&identity, + context, + desired_princ); + + if (!err) { + err = kim_ccache_create_from_client_identity (&kimccache, identity); + } + + if (!err) { + err = kim_ccache_get_state (kimccache, &state); + } + + if (!err && state != kim_credentials_state_valid) { + if (state == kim_credentials_state_needs_validation) { + err = kim_ccache_validate (kimccache, KIM_OPTIONS_DEFAULT); + } else { + kim_ccache_free (&kimccache); + ccache = NULL; + } + } + + if (!kimccache && kim_library_allow_automatic_prompting ()) { + /* ccache does not already exist, create a new one */ + err = kim_ccache_create_new (&kimccache, identity, + KIM_OPTIONS_DEFAULT); + } + + if (!err) { + err = kim_ccache_get_krb5_ccache (kimccache, context, &ccache); + } + + kim_ccache_free (&kimccache); + kim_identity_free (&identity); + + if (err) { + *minor_status = err; + return(GSS_S_CRED_UNAVAIL); + } + +#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_KIM || 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 = gss_krb5int_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; icount; 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; + +#ifndef LEAN_CLIENT + cred->keytab = NULL; +#endif /* LEAN_CLIENT */ + 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 */ +#ifndef LEAN_CLIENT + 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() */ + save_error_info(*minor_status, context); + krb5_free_context(context); + return(ret); + } +#endif /* LEAN_CLIENT */ + + /* 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) { +#ifndef LEAN_CLIENT + if (cred->keytab) + krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + if (cred->princ) + krb5_free_principal(context, cred->princ); + k5_mutex_destroy(&cred->lock); + xfree(cred); + /* minor_status set by acquire_init_cred() */ + save_error_info(*minor_status, context); + 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_NAME)) + if ((code = krb5_copy_principal(context, (krb5_principal) desired_name, + &(cred->princ)))) { + if (cred->ccache) + (void)krb5_cc_close(context, cred->ccache); +#ifndef LEAN_CLIENT + if (cred->keytab) + (void)krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + k5_mutex_destroy(&cred->lock); + xfree(cred); + *minor_status = code; + save_error_info(*minor_status, context); + 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); +#ifndef LEAN_CLIENT + if (cred->keytab) + (void)krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + if (cred->princ) + krb5_free_principal(context, cred->princ); + k5_mutex_destroy(&cred->lock); + xfree(cred); + *minor_status = code; + save_error_info(*minor_status, context); + 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); +#ifndef LEAN_CLIENT + if (cred->keytab) + (void)krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + 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); +#ifndef LEAN_CLIENT + if (cred->keytab) + (void)krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + if (cred->princ) + krb5_free_principal(context, cred->princ); + k5_mutex_destroy(&cred->lock); + xfree(cred); + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + save_error_string(*minor_status, "error saving credentials"); + 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); +} + +OM_uint32 +gss_krb5int_set_cred_rcache(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + krb5_gss_cred_id_t cred; + krb5_error_code code; + krb5_context context; + krb5_rcache rcache; + + assert(value->length == sizeof(rcache)); + + if (value->length != sizeof(rcache)) + return GSS_S_FAILURE; + + rcache = (krb5_rcache)value->value; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_NO_CRED; + + cred = (krb5_gss_cred_id_t)cred_handle; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + if (cred->rcache != NULL) { + code = krb5_rc_close(context, cred->rcache); + if (code) { + *minor_status = code; + krb5_free_context(context); + return GSS_S_FAILURE; + } + } + + cred->rcache = rcache; + + krb5_free_context(context); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/add_cred.c b/krb5-1-7/src/lib/gssapi/krb5/add_cred.c new file mode 100644 index 000000000..3652f918b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,388 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#else +#include +#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)) { + save_error_info(*minor_status, context); + 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))) { + save_error_info(*minor_status, context); + 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 ktboth[1024]; + const char *kttype, *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; + save_error_info(*minor_status, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } +#ifndef LEAN_CLIENT + 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; + save_error_info(*minor_status, context); + 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; + save_error_info(*minor_status, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } + } else { +#endif /* LEAN_CLIENT */ + new_cred->keytab = NULL; +#ifndef LEAN_CLIENT + } +#endif /* LEAN_CLIENT */ + + 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))) { +#ifndef LEAN_CLIENT + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); +#endif /* LEAN_CLIENT */ + if (new_cred->princ) + krb5_free_principal(context, new_cred->princ); + xfree(new_cred); + + *minor_status = code; + save_error_info(*minor_status, context); + krb5_free_context(context); + 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); +#ifndef LEAN_CLIENT + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); +#endif /* LEAN_CLIENT */ + 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); +#ifndef LEAN_CLIENT + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); +#endif /* LEAN_CLIENT */ + if (new_cred->princ) + krb5_free_principal(context, new_cred->princ); + xfree(new_cred); + + *minor_status = code; + save_error_info(*minor_status, context); + krb5_free_context(context); + 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); +#ifndef LEAN_CLIENT + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); +#endif /* LEAN_CLIENT */ + 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-7/src/lib/gssapi/krb5/canon_name.c b/krb5-1-7/src/lib/gssapi/krb5/canon_name.c new file mode 100644 index 000000000..b4f4d4bc1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/canon_name.c @@ -0,0 +1,46 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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(krb5_gss_duplicate_name(minor_status, input_name, output_name)); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/compare_name.c b/krb5-1-7/src/lib/gssapi/krb5/compare_name.c new file mode 100644 index 000000000..e456ed50a --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,61 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/gssapi/krb5/context_time.c b/krb5-1-7/src/lib/gssapi/krb5/context_time.c new file mode 100644 index 000000000..b263b50e6 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/context_time.c @@ -0,0 +1,69 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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; + save_error_info(*minor_status, ctx->k5_context); + return(GSS_S_FAILURE); + } + + if ((lifetime = ctx->krb_times.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-7/src/lib/gssapi/krb5/copy_ccache.c b/krb5-1-7/src/lib/gssapi/krb5/copy_ccache.c new file mode 100644 index 000000000..19fe1d788 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/copy_ccache.c @@ -0,0 +1,65 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +gss_krb5int_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + krb5_gss_cred_id_t k5creds; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_error_code code; + krb5_context context; + krb5_ccache out_ccache; + + assert(value->length == sizeof(out_ccache)); + + if (value->length != sizeof(out_ccache)) + return GSS_S_FAILURE; + + out_ccache = (krb5_ccache)value->value; + + /* cred handle will have been validated by gssspi_set_cred_option() */ + + 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; + save_error_info(*minor_status, context); + 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_free_cred_contents(context, &creds); + } + krb5_cc_end_seq_get(context, k5creds->ccache, &cursor); + k5_mutex_unlock(&k5creds->lock); + *minor_status = code; + if (code) + save_error_info(*minor_status, context); + krb5_free_context(context); + return code ? GSS_S_FAILURE : GSS_S_COMPLETE; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/delete_sec_context.c b/krb5-1-7/src/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 000000000..33e0e313e --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,125 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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))) { + save_error_info(*minor_status, context); + 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) + krb5_gss_release_oid(minor_status, &ctx->mech_used); + + if (ctx->authdata) + krb5_free_authdata(context, ctx->authdata); + + 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-7/src/lib/gssapi/krb5/deps b/krb5-1-7/src/lib/gssapi/krb5/deps new file mode 100644 index 000000000..b2a19f956 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/deps @@ -0,0 +1,657 @@ +# +# Generated makefile dependencies follow. +# +accept_sec_context.so accept_sec_context.po $(OUTPRE)accept_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h disp_status.c error_map.h \ + 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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.h \ + $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \ + gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h k5seal.c +k5sealiov.so k5sealiov.po $(OUTPRE)k5sealiov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealiov.c +k5sealv3.so k5sealv3.po $(OUTPRE)k5sealv3.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealv3.c +k5sealv3iov.so k5sealv3iov.po $(OUTPRE)k5sealv3iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealv3iov.c +k5unseal.so k5unseal.po $(OUTPRE)k5unseal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5unseal.c +k5unsealiov.so k5unsealiov.po $(OUTPRE)k5unsealiov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5unsealiov.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_ext.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/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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 diff --git a/krb5-1-7/src/lib/gssapi/krb5/disp_name.c b/krb5-1-7/src/lib/gssapi/krb5/disp_name.c new file mode 100644 index 000000000..d6bf0f7ba --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/disp_name.c @@ -0,0 +1,76 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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; + save_error_info(*minor_status, context); + 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-7/src/lib/gssapi/krb5/disp_status.c b/krb5-1-7/src/lib/gssapi/krb5/disp_status.c new file mode 100644 index 000000000..6cc1bc144 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/disp_status.c @@ -0,0 +1,197 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 "com_err.h" + +/* XXXX internationalization!! */ + +static inline int +compare_OM_uint32 (OM_uint32 a, OM_uint32 b) +{ + if (a < b) + return -1; + else if (a == b) + return 0; + else + return 1; +} +static inline void +free_string (char *s) +{ + free(s); +} +#include "error_map.h" +#include +char *get_error_message(OM_uint32 minor_code) +{ + gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); + char *msg = NULL; +#ifdef DEBUG + fprintf(stderr, "%s(%lu, p=%p)", __func__, (unsigned long) minor_code, + (void *) p); +#endif + if (p) { + char **v = gsserrmap_find(p, minor_code); + if (v) { + msg = *v; +#ifdef DEBUG + fprintf(stderr, " FOUND!"); +#endif + } + } + if (msg == 0) + msg = (char *)error_message((krb5_error_code)minor_code); +#ifdef DEBUG + fprintf(stderr, " -> %p/%s\n", (void *) msg, msg); +#endif + return msg; +} +#define save_error_string_nocopy gss_krb5_save_error_string_nocopy +static int save_error_string_nocopy(OM_uint32 minor_code, char *msg) +{ + gsserrmap *p; + int ret; + +#ifdef DEBUG + fprintf(stderr, "%s(%lu, %s)", __func__, (unsigned long) minor_code, msg); +#endif + p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); + if (!p) { + p = malloc(sizeof(*p)); + if (p == NULL) { + ret = 1; + goto fail; + } + if (gsserrmap_init(p) != 0) { + free(p); + p = NULL; + ret = 1; + goto fail; + } + if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) { + gsserrmap_destroy(p); + free(p); + p = NULL; + ret = 1; + goto fail; + } + } + ret = gsserrmap_replace_or_insert(p, minor_code, msg); +fail: +#ifdef DEBUG + fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS"); +#endif + return ret; +} +void save_error_string(OM_uint32 minor_code, char *msg) +{ + char *s = strdup(msg); + if (s) { + if (save_error_string_nocopy(minor_code, s) != 0) + free(s); + } +} +void save_error_message(OM_uint32 minor_code, const char *format, ...) +{ + char *s; + int n; + va_list ap; + + va_start(ap, format); + n = vasprintf(&s, format, ap); + va_end(ap); + if (n >= 0) { + if (save_error_string_nocopy(minor_code, s) != 0) + free(s); + } +} +void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx) +{ + char *s; + +#ifdef DEBUG + fprintf(stderr, "%s(%lu, ctx=%p)\n", __func__, + (unsigned long) minor_code, (void *)ctx); +#endif + s = (char *)krb5_get_error_message(ctx, (krb5_error_code)minor_code); +#ifdef DEBUG + fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __func__, + (unsigned long) minor_code, (void *)ctx, s); +#endif + save_error_string(minor_code, s); + /* The get_error_message call above resets the error message in + ctx. Put it back, in case we make this call again *sigh*. */ + krb5_set_error_message(ctx, (krb5_error_code)minor_code, "%s", s); + krb5_free_error_message(ctx, s); +} +void krb5_gss_delete_error_info(void *p) +{ + gsserrmap_destroy(p); +} + +/**/ + +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) gss_krb5int_initialize_library(); + + if (*message_context) { + *minor_status = (OM_uint32) G_BAD_MSG_CTX; + return(GSS_S_FAILURE); + } + + /* If this fails, there's not much we can do... */ + if (g_make_string_buffer(krb5_gss_get_error_message(status_value), + status_string) != 0) + *minor_status = ENOMEM; + else + *minor_status = 0; + return 0; + } else { + *minor_status = 0; + return(GSS_S_BAD_STATUS); + } +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/duplicate_name.c b/krb5-1-7/src/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 000000000..add3a2ed0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,75 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/duplicate_name.c + * + * Copyright 1997,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. + * + */ + +#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; + save_error_info(*minor_status, context); + 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-7/src/lib/gssapi/krb5/export_name.c b/krb5-1-7/src/lib/gssapi/krb5/export_name.c new file mode 100644 index 000000000..46664e5a0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/export_name.c @@ -0,0 +1,97 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/export_name.c + * + * Copyright 1997, 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. + * + */ + +#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; + unsigned char *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; + save_error_info((OM_uint32)code, context); + 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; + store_16_be(gss_mech_krb5->length+2, cp); + cp += 2; + *cp++ = 0x06; + *cp++ = (gss_mech_krb5->length) & 0xFF; + memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length); + cp += gss_mech_krb5->length; + store_32_be(length, cp); + cp += 4; + memcpy(cp, str, length); + + free(str); + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/export_sec_context.c b/krb5-1-7/src/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 000000000..f408d09ff --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,107 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/export_sec_context.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#ifndef LEAN_CLIENT +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 = NULL; + 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 (retval != GSS_S_COMPLETE) + if (kret != 0 && context != 0) + save_error_info((OM_uint32)kret, context); + if (obuffer && bufsize) { + memset(obuffer, 0, bufsize); + xfree(obuffer); + } + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + return(retval); +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1-7/src/lib/gssapi/krb5/get_tkt_flags.c b/krb5-1-7/src/lib/gssapi/krb5/get_tkt_flags.c new file mode 100644 index 000000000..29126d6c8 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/get_tkt_flags.c @@ -0,0 +1,45 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + gss_buffer_desc rep; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + rep.value = &ctx->krb_flags; + rep.length = sizeof(ctx->krb_flags); + + return generic_gss_add_buffer_set_member(minor_status, &rep, data_set); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/gssapiP_krb5.h b/krb5-1-7/src/lib/gssapi/krb5/gssapiP_krb5.h new file mode 100644 index 000000000..3c4f7e038 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -0,0 +1,933 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#ifdef HAVE_MEMORY_H +#include +#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" +#include "gssapi_ext.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_MIC_MSG 0x0404 +#define KG2_TOK_WRAP_MSG 0x0504 +#define KG2_TOK_DEL_CTX 0x0405 + +#define KRB5_GSS_FOR_CREDS_OPTION 1 + +#define KG2_RESP_FLAG_ERROR 0x0001 +#define KG2_RESP_FLAG_DELEG_OK 0x0002 + +/** CFX flags **/ +#define FLAG_SENDER_IS_ACCEPTOR 0x01 +#define FLAG_WRAP_CONFIDENTIAL 0x02 +#define FLAG_ACCEPTOR_SUBKEY 0x04 + +/* 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_ticket_times krb_times; + 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_authdata **authdata; +} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; + +extern g_set kg_vdb; + +#ifndef LEAN_CLIENT +extern k5_mutex_t gssint_krb5_keytab_lock; +#endif /* LEAN_CLIENT */ + +/* 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); + +krb5_error_code +kg_setup_keys(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + krb5_keyblock *subkey, + krb5_cksumtype *cksumtype); + +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_encrypt_iov (krb5_context context, + int proto, int dce_style, + size_t ec, size_t rrc, + krb5_keyblock *key, int usage, + krb5_pointer iv, + gss_iov_buffer_desc *iov, + int iov_count); + +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_arcfour_docrypt_iov (krb5_context context, + const krb5_keyblock *longterm_key , int ms_usage, + const unsigned char *kd_data, size_t kd_data_len, + gss_iov_buffer_desc *iov, + int iov_count); + +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); + +krb5_error_code kg_decrypt_iov (krb5_context context, + int proto, int dce_style, + size_t ec, size_t rrc, + krb5_keyblock *key, int usage, + krb5_pointer iv, + gss_iov_buffer_desc *iov, + int iov_count); + +OM_uint32 kg_seal (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, + 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, + gss_qop_t *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); + +/* AEAD */ + +krb5_error_code gss_krb5int_make_seal_token_v3_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 gss_krb5int_unseal_v3_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + int *conf_state, + gss_qop_t *qop_state, + int toktype); + +gss_iov_buffer_t kg_locate_iov (gss_iov_buffer_desc *iov, + int iov_count, + OM_uint32 type); + +void kg_iov_msglen(gss_iov_buffer_desc *iov, + int iov_count, + size_t *data_length, + size_t *assoc_data_length); + +void kg_release_iov(gss_iov_buffer_desc *iov, + int iov_count); + +krb5_error_code kg_make_checksum_iov_v1(krb5_context context, + krb5_cksumtype type, + size_t token_cksum_len, + krb5_keyblock *seq, + krb5_keyblock *enc, /* for conf len */ + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_checksum *checksum); + +krb5_error_code kg_make_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count); + +krb5_error_code kg_verify_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + krb5_boolean *valid); + +OM_uint32 kg_seal_iov (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 kg_unseal_iov (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 kg_seal_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count); + +krb5_cryptotype kg_translate_flag_iov(OM_uint32 type); + +OM_uint32 kg_fixup_padding_iov(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count); + +int kg_map_toktype(int proto, int toktype); + +krb5_boolean kg_integ_only_iov(gss_iov_buffer_desc *iov, int iov_count); + +krb5_error_code kg_allocate_iov(gss_iov_buffer_t iov, size_t size); + +/** 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 */ +); + +#ifndef LEAN_CLIENT +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 */ +); +#endif /* LEAN_CLIENT */ + +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_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_wrap_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 +krb5_gss_wrap_iov_length +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +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_unwrap_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +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 */ +); +#ifndef LEAN_CLIENT +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 */ +); +#endif /* LEAN_CLIENT */ + +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, + unsigned int bodysize, + gss_buffer_t message_buffer, + int *conf_state, gss_qop_t *qop_state, + int toktype); + +int gss_krb5int_rotate_left (void *ptr, size_t bufsiz, size_t rc); + +/* + * These take unglued krb5-mech-specific contexts. + */ + +#define GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH 11 +#define GSS_KRB5_GET_TKT_FLAGS_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x01" + +OM_uint32 KRB5_CALLCONV gss_krb5int_get_tkt_flags +(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +#define GSS_KRB5_COPY_CCACHE_OID_LENGTH 11 +#define GSS_KRB5_COPY_CCACHE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x02" + +OM_uint32 KRB5_CALLCONV gss_krb5int_copy_ccache +(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value); + +#define GSS_KRB5_CCACHE_NAME_OID_LENGTH 11 +#define GSS_KRB5_CCACHE_NAME_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x03" + +struct krb5_gss_ccache_name_req { + const char *name; + const char **out_name; +}; + +OM_uint32 KRB5_CALLCONV gss_krb5int_ccache_name + (OM_uint32 *minor_status, + const gss_OID, + const gss_OID, + const gss_buffer_t); + +#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH 11 +#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x04" + +struct krb5_gss_set_allowable_enctypes_req { + OM_uint32 num_ktypes; + krb5_enctype *ktypes; +}; + +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" + +OM_uint32 +gss_krb5int_inq_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); + +OM_uint32 KRB5_CALLCONV +gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred, + const gss_OID desired_oid, + const gss_buffer_t value); + +#define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06" + +OM_uint32 +gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +#define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07" + +OM_uint32 +gss_krb5int_free_lucid_sec_context(OM_uint32 *, const gss_OID, + const gss_OID, gss_buffer_t); + +extern k5_mutex_t kg_kdc_flag_mutex; +krb5_error_code krb5_gss_init_context (krb5_context *ctxp); + +#define GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_USE_KDC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x08" + +OM_uint32 krb5int_gss_use_kdc_context(OM_uint32 *, const gss_OID, + const gss_OID, gss_buffer_t); + +krb5_error_code krb5_gss_use_kdc_context(void); + +#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH 11 +#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x09" + +OM_uint32 +gss_krb5int_register_acceptor_identity(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); + +#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" + +OM_uint32 +gss_krb5int_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *ad_data); + +#define GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH 11 +#define GSS_KRB5_SET_CRED_RCACHE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0b" + +OM_uint32 +gss_krb5int_set_cred_rcache(OM_uint32 *, gss_cred_id_t, const gss_OID, const gss_buffer_t); + +#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c" + +OM_uint32 +gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *, + const gss_ctx_id_t, + const gss_OID, + gss_buffer_set_t *); + +#ifdef _GSS_STATIC_LINK +int gss_krb5int_lib_init(void); +void gss_krb5int_lib_fini(void); +#endif /* _GSS_STATIC_LINK */ + +OM_uint32 gss_krb5int_initialize_library(void); +void gss_krb5int_cleanup_library(void); + +/* For error message handling. */ +/* Returns a shared string, not a private copy! */ +extern char * +krb5_gss_get_error_message(OM_uint32 minor_code); +extern void +krb5_gss_save_error_string(OM_uint32 minor_code, char *msg); +extern void +krb5_gss_save_error_message(OM_uint32 minor_code, const char *format, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + extern void + krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx); +#define get_error_message krb5_gss_get_error_message +#define save_error_string krb5_gss_save_error_string +#define save_error_message krb5_gss_save_error_message +#define save_error_info krb5_gss_save_error_info +extern void krb5_gss_delete_error_info(void *p); + +/* Prefix concatenated with Kerberos encryption type */ +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10 +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04" + +#endif /* _GSSAPIP_KRB5_H_ */ diff --git a/krb5-1-7/src/lib/gssapi/krb5/gssapi_err_krb5.et b/krb5-1-7/src/lib/gssapi/krb5/gssapi_err_krb5.et new file mode 100644 index 000000000..c2a705c84 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/gssapi/krb5/gssapi_krb5.c b/krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.c new file mode 100644 index 000000000..6e1d61869 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.c @@ -0,0 +1,799 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + */ +/* + * Copyright (c) 2006-2008, 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. + */ + +/* + * $Id$ + */ + + +/* For declaration of krb5_ser_context_init */ +#include "k5-int.h" +#include "gssapiP_krb5.h" +#include "mglueP.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 + * Provisionally reserved for Kerberos session key algorithm + * identifiers is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_enctype(4) = 1.2.840.113554.1.2.2.4 + * Provisionally reserved for Kerberos mechanism-specific APIs: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_gssapi_ext(5) = 1.2.840.113554.1.2.2.5 + */ + +/* + * 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 = ENOMEM; + } 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 = ENOMEM; + } + } + if (err && context) + save_error_info(err, context); + 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 = strdup(name); + if (new_name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } + + 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; +} + +#define g_OID_prefix_equal(o1, o2) \ + (((o1)->length >= (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0)) + +/* + * gss_inquire_sec_context_by_oid() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); +} krb5_gss_inquire_sec_context_by_oid_ops[] = { + { + {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID}, + gss_krb5int_get_tkt_flags + }, + { + {GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID}, + gss_krb5int_extract_authz_data_from_sec_context + }, + { + {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID}, + gss_krb5int_inq_session_key + }, + { + {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID}, + gss_krb5int_export_lucid_sec_context + }, + { + {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID}, + gss_krb5int_extract_authtime_from_sec_context + } +}; + +static OM_uint32 +krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *data_set = GSS_C_NO_BUFFER_SET; + + if (!kg_validate_ctx_id(context_handle)) + return GSS_S_NO_CONTEXT; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (!ctx->established) + return GSS_S_NO_CONTEXT; + + for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/ + sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) { + return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status, + context_handle, + desired_object, + data_set); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gss_inquire_cred_by_oid() methods + */ +#if 0 +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *); +} krb5_gss_inquire_cred_by_oid_ops[] = { +}; +#endif + +static OM_uint32 +krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major_status = GSS_S_FAILURE; + krb5_gss_cred_id_t cred; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *data_set = GSS_C_NO_BUFFER_SET; + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED; + return GSS_S_NO_CRED; + } + + major_status = krb5_gss_validate_cred(minor_status, cred_handle); + if (GSS_ERROR(major_status)) + return major_status; + + cred = (krb5_gss_cred_id_t) cred_handle; + +#if 0 + for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/ + sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) { + return (*krb5_gss_inquire_cred_by_oid_ops[i].func)(minor_status, + cred_handle, + desired_object, + data_set); + } + } +#endif + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gss_set_sec_context_option() methods + */ +#if 0 +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, gss_ctx_id_t *, const gss_OID, const gss_buffer_t); +} krb5_gss_set_sec_context_option_ops[] = { +}; +#endif + +static OM_uint32 +krb5_gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (*context_handle != GSS_C_NO_CONTEXT) { + krb5_gss_ctx_id_rec *ctx; + + if (!kg_validate_ctx_id(*context_handle)) + return GSS_S_NO_CONTEXT; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (!ctx->established) + return GSS_S_NO_CONTEXT; + } + +#if 0 + for (i = 0; i < sizeof(krb5_gss_set_sec_context_option_ops)/ + sizeof(krb5_gss_set_sec_context_option_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gss_set_sec_context_option_ops[i].oid)) { + return (*krb5_gss_set_sec_context_option_ops[i].func)(minor_status, + context_handle, + desired_object, + value); + } + } +#endif + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gssspi_set_cred_option() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t, const gss_OID, const gss_buffer_t); +} krb5_gssspi_set_cred_option_ops[] = { + { + {GSS_KRB5_COPY_CCACHE_OID_LENGTH, GSS_KRB5_COPY_CCACHE_OID}, + gss_krb5int_copy_ccache + }, + { + {GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID}, + gss_krb5int_set_allowable_enctypes + }, + { + {GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, GSS_KRB5_SET_CRED_RCACHE_OID}, + gss_krb5int_set_cred_rcache + } +}; + +static OM_uint32 +krb5_gssspi_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 major_status = GSS_S_FAILURE; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED; + return GSS_S_NO_CRED; + } + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + major_status = krb5_gss_validate_cred(minor_status, cred_handle); + if (GSS_ERROR(major_status)) + return major_status; + + for (i = 0; i < sizeof(krb5_gssspi_set_cred_option_ops)/ + sizeof(krb5_gssspi_set_cred_option_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gssspi_set_cred_option_ops[i].oid)) { + return (*krb5_gssspi_set_cred_option_ops[i].func)(minor_status, + cred_handle, + desired_object, + value); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gssspi_mech_invoke() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); +} krb5_gssspi_mech_invoke_ops[] = { + { + {GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID}, + gss_krb5int_register_acceptor_identity + }, + { + {GSS_KRB5_CCACHE_NAME_OID_LENGTH, GSS_KRB5_CCACHE_NAME_OID}, + gss_krb5int_ccache_name + }, + { + {GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID}, + gss_krb5int_free_lucid_sec_context + }, + { + {GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, GSS_KRB5_USE_KDC_CONTEXT_OID}, + krb5int_gss_use_kdc_context + } +}; + +static OM_uint32 +krb5_gssspi_mech_invoke (OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_mech == GSS_C_NO_OID) + return GSS_S_BAD_MECH; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + for (i = 0; i < sizeof(krb5_gssspi_mech_invoke_ops)/ + sizeof(krb5_gssspi_mech_invoke_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gssspi_mech_invoke_ops[i].oid)) { + return (*krb5_gssspi_mech_invoke_ops[i].func)(minor_status, + desired_mech, + desired_object, + value); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +static struct gss_config krb5_mechanism = { + { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID }, + NULL, + krb5_gss_acquire_cred, + krb5_gss_release_cred, + krb5_gss_init_sec_context, +#ifdef LEAN_CLIENT + NULL, +#else + krb5_gss_accept_sec_context, +#endif + krb5_gss_process_context_token, + krb5_gss_delete_sec_context, + krb5_gss_context_time, + krb5_gss_get_mic, + krb5_gss_verify_mic, +#ifdef IOV_SHIM_EXERCISE + NULL, + NULL, +#else + krb5_gss_wrap, + krb5_gss_unwrap, +#endif + krb5_gss_display_status, + krb5_gss_indicate_mechs, + krb5_gss_compare_name, + krb5_gss_display_name, + krb5_gss_import_name, + krb5_gss_release_name, + krb5_gss_inquire_cred, + krb5_gss_add_cred, +#ifdef LEAN_CLIENT + NULL, + NULL, +#else + krb5_gss_export_sec_context, + krb5_gss_import_sec_context, +#endif + krb5_gss_inquire_cred_by_mech, + krb5_gss_inquire_names_for_mech, + krb5_gss_inquire_context, + krb5_gss_internal_release_oid, + krb5_gss_wrap_size_limit, + krb5_gss_export_name, + NULL, /* store_cred */ + krb5_gss_inquire_sec_context_by_oid, + krb5_gss_inquire_cred_by_oid, + krb5_gss_set_sec_context_option, + krb5_gssspi_set_cred_option, + krb5_gssspi_mech_invoke, + NULL, /* wrap_aead */ + NULL, /* unwrap_aead */ + krb5_gss_wrap_iov, + krb5_gss_unwrap_iov, + krb5_gss_wrap_iov_length, + NULL, /* complete_auth_token */ +}; + + +#ifdef _GSS_STATIC_LINK +#include "mglueP.h" +static int gss_krb5mechglue_init(void) +{ + struct gss_mech_config mech_krb5; + + memset(&mech_krb5, 0, sizeof(mech_krb5)); + mech_krb5.mech = &krb5_mechanism; + mech_krb5.mechNameStr = "kerberos_v5"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5; + + gssint_register_mechinfo(&mech_krb5); + + mech_krb5.mechNameStr = "kerberos_v5_old"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5_old; + gssint_register_mechinfo(&mech_krb5); + + mech_krb5.mechNameStr = "mskrb"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5_wrong; + gssint_register_mechinfo(&mech_krb5); + + return 0; +} +#else +MAKE_INIT_FUNCTION(gss_krb5int_lib_init); +MAKE_FINI_FUNCTION(gss_krb5int_lib_fini); + +gss_mechanism KRB5_CALLCONV +gss_mech_initialize(void) +{ + return &krb5_mechanism; +} +#endif /* _GSS_STATIC_LINK */ + +int gss_krb5int_lib_init(void) +{ + int err; + +#ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_init\n"); +#endif + + add_error_table(&et_ggss_error_table); + +#ifndef LEAN_CLIENT + err = k5_mutex_finish_init(&gssint_krb5_keytab_lock); + if (err) + return err; +#endif /* LEAN_CLIENT */ + 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; + err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE, + krb5_gss_delete_error_info); + if (err) + return err; +#ifndef _WIN32 + err = k5_mutex_finish_init(&kg_kdc_flag_mutex); + if (err) + return err; + err = k5_mutex_finish_init(&kg_vdb.mutex); + if (err) + return err; +#endif +#ifdef _GSS_STATIC_LINK + err = gss_krb5mechglue_init(); + if (err) + return err; +#endif + + return 0; +} + +void gss_krb5int_lib_fini(void) +{ +#ifndef _GSS_STATIC_LINK + if (!INITIALIZER_RAN(gss_krb5int_lib_init) || PROGRAM_EXITING()) { +# ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_fini: skipping\n"); +# endif + return; + } +#endif +#ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_fini\n"); +#endif + remove_error_table(&et_k5g_error_table); + + 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 +#ifndef LEAN_CLIENT + k5_mutex_destroy(&gssint_krb5_keytab_lock); +#endif /* LEAN_CLIENT */ +} + +#ifdef _GSS_STATIC_LINK +extern OM_uint32 gssint_lib_init(void); +#endif + +OM_uint32 gss_krb5int_initialize_library (void) +{ +#ifdef _GSS_STATIC_LINK + return gssint_mechglue_initialize_library(); +#else + return CALL_INIT_FUNCTION(gss_krb5int_lib_init); +#endif +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.hin b/krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.hin new file mode 100644 index 000000000..783387a52 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/gssapi_krb5.hin @@ -0,0 +1,288 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#include +#include + +/* 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 +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); + + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data); + +OM_uint32 KRB5_CALLCONV +gss_krb5_set_cred_rcache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_rcache rcache); + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, krb5_timestamp *); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GSSAPI_KRB5_H_ */ diff --git a/krb5-1-7/src/lib/gssapi/krb5/import_name.c b/krb5-1-7/src/lib/gssapi/krb5/import_name.c new file mode 100644 index 000000000..440d36222 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/import_name.c @@ -0,0 +1,254 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#include +#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; + unsigned char *cp, *end; + char *stringrep, *tmp, *tmp2; + 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; + save_error_info(*minor_status, context); + 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)) { +#define BOUNDS_CHECK(cp, end, n) do { if ((end) - (cp) < (n)) \ + goto fail_name; } while (0) + cp = (unsigned char *)tmp; + end = cp + input_name_buffer->length; + + BOUNDS_CHECK(cp, end, 4); + if (*cp++ != 0x04) + goto fail_name; + if (*cp++ != 0x01) + goto fail_name; + if (*cp++ != 0x00) + goto fail_name; + length = *cp++; + if (length != (ssize_t)gss_mech_krb5->length+2) + goto fail_name; + + BOUNDS_CHECK(cp, end, 2); + if (*cp++ != 0x06) + goto fail_name; + length = *cp++; + if (length != gss_mech_krb5->length) + goto fail_name; + + BOUNDS_CHECK(cp, end, length); + if (memcmp(cp, gss_mech_krb5->elements, length) != 0) + goto fail_name; + cp += length; + + BOUNDS_CHECK(cp, end, 4); + length = *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + + BOUNDS_CHECK(cp, end, length); + tmp2 = malloc(length+1); + if (tmp2 == NULL) { + xfree(tmp); + *minor_status = ENOMEM; + krb5_free_context(context); + return GSS_S_FAILURE; + } + strncpy(tmp2, (char *)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; + save_error_info(*minor_status, context); + 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-7/src/lib/gssapi/krb5/import_sec_context.c b/krb5-1-7/src/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 000000000..b31d7acf1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,129 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/import_sec_context.c + * + * Copyright 1995,2004,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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)) { + generic_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, + }; + unsigned 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) { + *minor_status = kret; + save_error_info(*minor_status, context); + krb5_free_context(context); + 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; + save_error_info(*minor_status, context); + 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-7/src/lib/gssapi/krb5/indicate_mechs.c b/krb5-1-7/src/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 000000000..d744af724 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,37 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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; +{ + return generic_gss_copy_oid_set(minor_status, gss_mech_set_krb5_both, mech_set); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/init_sec_context.c b/krb5-1-7/src/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 000000000..0f1294834 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,1017 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2002, 2003, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ +/* + * Copyright (c) 2006-2008, 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" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include + +/* + * $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 | + GSS_C_DELEG_POLICY_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 = (unsigned char *)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 | AP_OPTS_ETYPE_NEGOTIATION; + + 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->krb_times = k_cred->times; + ctx->krb_flags = k_cred->ticket_flags; + + /* build up the token */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* + * For DCE RPC, do not encapsulate the AP-REQ in the + * typical GSS wrapping. + */ + token->length = ap_req.length; + token->value = ap_req.data; + + ap_req.data = NULL; /* don't double free */ + } else { + /* 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); +} + +/* + * 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 | + GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | + GSS_C_EXTENDED_ERROR_FLAG))); + ctx->seed_init = 0; + ctx->big_endian = 0; /* all initiators do little-endian, as per spec */ + ctx->seqstate = 0; + + if (req_flags & GSS_C_DCE_STYLE) + ctx->gss_flags |= GSS_C_MUTUAL_FLAG; + + if ((code = krb5_timeofday(context, &now))) + goto fail; + + if (time_req == 0 || time_req == GSS_C_INDEFINITE) { + ctx->krb_times.endtime = 0; + } else { + ctx->krb_times.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->krb_times.endtime, &k_cred); + if (code) + goto fail; + + ctx->krb_times = k_cred->times; + + /* + * GSS_C_DELEG_POLICY_FLAG means to delegate only if the + * ok-as-delegate ticket flag is set. + */ + if ((req_flags & GSS_C_DELEG_POLICY_FLAG) + && (k_cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)) + ctx->gss_flags |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG; + + 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_int32 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); + } + + krb5_free_creds(context, k_cred); + k_cred = NULL; + ctx->enc = NULL; + ctx->seq = NULL; + ctx->have_acceptor_subkey = 0; + code = kg_setup_keys(context, ctx, ctx->subkey, &ctx->cksumtype); + if (code != 0) + goto fail; + + /* 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->krb_times.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 (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* Raw AP-REP */ + ap_rep.length = input_token->length; + ap_rep.data = (char *)input_token->value; + } else 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 = (krb5_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 (ap_rep_data->subkey != NULL && + (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) || + ap_rep_data->subkey->enctype != ctx->subkey->enctype)) { + /* Keep acceptor's subkey. */ + ctx->have_acceptor_subkey = 1; + code = krb5_copy_keyblock(context, ap_rep_data->subkey, + &ctx->acceptor_subkey); + if (code) { + krb5_free_ap_rep_enc_part(context, ap_rep_data); + goto fail; + } + code = kg_setup_keys(context, ctx, ctx->acceptor_subkey, + &ctx->acceptor_subkey_cksumtype); + if (code) { + krb5_free_ap_rep_enc_part(context, ap_rep_data); + goto fail; + } + } + /* free the ap_rep_data */ + krb5_free_ap_rep_enc_part(context, ap_rep_data); + + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + krb5_data outbuf; + + code = krb5_mk_rep_dce(context, ctx->auth_context, &outbuf); + if (code) + goto fail; + + output_token->value = outbuf.data; + output_token->length = outbuf.length; + } + + /* set established */ + ctx->established = 1; + + /* set returns */ + + if (time_rec) { + if ((code = krb5_timeofday(context, &now))) + goto fail; + *time_rec = ctx->krb_times.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))) { + save_error_info(*minor_status, context); + krb5_free_context(context); + 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; + save_error_info(*minor_status, context); + 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)) { + save_error_info(*minor_status, context); + 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) { + if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) + krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred); + 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) { + save_error_info (*minor_status, 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 = gss_krb5int_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 +OM_uint32 +krb5int_gss_use_kdc_context(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 err; + + *minor_status = 0; + + err = gss_krb5int_initialize_library(); + if (err) + return err; + *minor_status = k5_mutex_lock(&kg_kdc_flag_mutex); + if (*minor_status) { + return GSS_S_FAILURE; + } + kdc_flag = 1; + k5_mutex_unlock(&kg_kdc_flag_mutex); + return GSS_S_COMPLETE; +} +#endif diff --git a/krb5-1-7/src/lib/gssapi/krb5/inq_context.c b/krb5-1-7/src/lib/gssapi/krb5/inq_context.c new file mode 100644 index 000000000..f3e44cdf5 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/inq_context.c @@ -0,0 +1,313 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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) 2006-2008, 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 (c) 2006-2008, 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 "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, opened) + 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 *opened; +{ + krb5_context context; + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx; + krb5_principal initiator, acceptor; + 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); + } + + initiator = NULL; + acceptor = NULL; + context = ctx->k5_context; + + if ((code = krb5_timeofday(context, &now))) { + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + + if ((lifetime = ctx->krb_times.endtime - now) < 0) + lifetime = 0; + + if (initiator_name) { + if ((code = krb5_copy_principal(context, + ctx->initiate?ctx->here:ctx->there, + &initiator))) { + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + if (! kg_save_name((gss_name_t) initiator)) { + krb5_free_principal(context, initiator); + *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, + &acceptor))) { + if (initiator) krb5_free_principal(context, initiator); + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + if (! kg_save_name((gss_name_t) acceptor)) { + krb5_free_principal(context, acceptor); + if (initiator) { + kg_delete_name((gss_name_t) initiator); + krb5_free_principal(context, initiator); + } + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_FAILURE); + } + } + + if (initiator_name) + *initiator_name = (gss_name_t) initiator; + + if (acceptor_name) + *acceptor_name = (gss_name_t) acceptor; + + 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 (opened) + *opened = ctx->established; + + *minor_status = 0; + return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); +} + +OM_uint32 +gss_krb5int_inq_session_key( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + krb5_keyblock *key; + gss_buffer_desc keyvalue, keyinfo; + OM_uint32 major_status, minor; + unsigned char oid_buf[GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH + 6]; + gss_OID_desc oid; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey; + + keyvalue.value = key->contents; + keyvalue.length = key->length; + + major_status = generic_gss_add_buffer_set_member(minor_status, &keyvalue, data_set); + if (GSS_ERROR(major_status)) + goto cleanup; + + oid.elements = oid_buf; + oid.length = sizeof(oid_buf); + + major_status = generic_gss_oid_compose(minor_status, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH, + key->enctype, + &oid); + if (GSS_ERROR(major_status)) + goto cleanup; + + keyinfo.value = oid.elements; + keyinfo.length = oid.length; + + major_status = generic_gss_add_buffer_set_member(minor_status, &keyinfo, data_set); + if (GSS_ERROR(major_status)) + goto cleanup; + + return GSS_S_COMPLETE; + +cleanup: + if (*data_set != GSS_C_NO_BUFFER_SET) { + if ((*data_set)->count != 0) + memset((*data_set)->elements[0].value, 0, (*data_set)->elements[0].length); + gss_release_buffer_set(&minor, data_set); + } + + return major_status; +} + +OM_uint32 +gss_krb5int_extract_authz_data_from_sec_context( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major_status; + krb5_gss_ctx_id_rec *ctx; + int ad_type = 0; + size_t i; + + *data_set = GSS_C_NO_BUFFER_SET; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + major_status = generic_gss_oid_decompose(minor_status, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, + desired_object, + &ad_type); + if (major_status != GSS_S_COMPLETE || ad_type == 0) { + *minor_status = ENOENT; + return GSS_S_FAILURE; + } + + if (ctx->authdata != NULL) { + for (i = 0; ctx->authdata[i] != NULL; i++) { + if (ctx->authdata[i]->ad_type == ad_type) { + gss_buffer_desc ad_data; + + ad_data.length = ctx->authdata[i]->length; + ad_data.value = ctx->authdata[i]->contents; + + major_status = generic_gss_add_buffer_set_member(minor_status, + &ad_data, data_set); + if (GSS_ERROR(major_status)) + break; + } + } + } + + if (GSS_ERROR(major_status)) { + OM_uint32 tmp; + + generic_gss_release_buffer_set(&tmp, data_set); + } + + return major_status; +} + +OM_uint32 +gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_oid, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + gss_buffer_desc rep; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + rep.value = &ctx->krb_times.authtime; + rep.length = sizeof(ctx->krb_times.authtime); + + return generic_gss_add_buffer_set_member(minor_status, &rep, data_set); +} + diff --git a/krb5-1-7/src/lib/gssapi/krb5/inq_cred.c b/krb5-1-7/src/lib/gssapi/krb5/inq_cred.c new file mode 100644 index 000000000..8560135ab --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/inq_cred.c @@ -0,0 +1,268 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ +/* + * 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; + save_error_info(*minor_status, context); + 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) generic_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-7/src/lib/gssapi/krb5/inq_names.c b/krb5-1-7/src/lib/gssapi/krb5/inq_names.c new file mode 100644 index 000000000..5db0ae0ee --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/inq_names.c @@ -0,0 +1,99 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 = generic_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) generic_gss_release_oid_set(&minor, name_types); + } + return(major); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5seal.c b/krb5-1-7/src/lib/gssapi/krb5/k5seal.c new file mode 100644 index 000000000..1949020ab --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5seal.c @@ -0,0 +1,399 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 + +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 do_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 int conflen=0, tmsglen, tlen, msglen; + unsigned char *t, *ptr; + unsigned char *plain; + unsigned char pad; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + + + assert((!do_encrypt) || (toktype == KG_TOK_SEAL_MSG)); + /* create the token buffer */ + /* Do we need confounder? */ + if (do_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 */ + store_16_le(signalg, &ptr[0]); + + /* 2..3 SEAL_ALG or Filler */ + if ((toktype == KG_TOK_SEAL_MSG) && do_encrypt) { + store_16_le(sealalg, &ptr[2]); + } 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) { + xfree(t); + 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, + (krb5_ui_4)*seqnum, ptr+14, ptr+6))) { + xfree (plain); + xfree(t); + return(code); + } + + if (do_encrypt) { + switch(sealalg) { + case SEAL_ALG_MICROSOFT_RC4: + { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + int i; + store_32_be(*seqnum, bigend_seqnum); + 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; + gss_qop_t 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; + save_error_info(*minor_status, context); + 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; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + + if (conf_state) + *conf_state = conf_req_flag; + + *minor_status = 0; + return((ctx->krb_times.endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5sealiov.c b/krb5-1-7/src/lib/gssapi/krb5/k5sealiov.c new file mode 100644 index 000000000..f4354a9f3 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5sealiov.c @@ -0,0 +1,511 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/k5sealiov.c + * + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5-platform.h" /* for 64-bit support */ +#include "k5-int.h" /* for zap() */ +#include "gssapiP_krb5.h" +#include + +static krb5_error_code +make_seal_token_v1_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code = 0; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + krb5_checksum md5cksum; + krb5_checksum cksum; + size_t k5_headerlen = 0, k5_trailerlen = 0; + size_t data_length = 0, assoc_data_length = 0; + size_t tmsglen = 0, tlen; + unsigned char *ptr; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + + assert(toktype == KG_TOK_WRAP_MSG); + + md5cksum.length = cksum.length = 0; + md5cksum.contents = cksum.contents = NULL; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) + return EINVAL; + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding == NULL && (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) + return EINVAL; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL) + trailer->buffer.length = 0; + + /* Determine confounder length */ + if (toktype == KG_TOK_WRAP_MSG || conf_req_flag) + k5_headerlen = kg_confounder_size(context, ctx->enc); + + /* Check padding length */ + if (toktype == KG_TOK_WRAP_MSG) { + size_t k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; + size_t gss_padlen; + size_t conf_data_length; + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + conf_data_length = k5_headerlen + data_length - assoc_data_length; + + if (k5_padlen == 1) + gss_padlen = 1; /* one byte to indicate one byte of padding */ + else + gss_padlen = k5_padlen - (conf_data_length % k5_padlen); + + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* DCE will pad the actual data itself; padding buffer optional and will be zeroed */ + gss_padlen = 0; + + if (conf_data_length % k5_padlen) + code = KRB5_BAD_MSIZE; + } else if (padding->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(padding, gss_padlen); + } else if (padding->buffer.length < gss_padlen) { + code = KRB5_BAD_MSIZE; + } + if (code != 0) + goto cleanup; + + /* Initialize padding buffer to pad itself */ + if (padding != NULL) { + padding->buffer.length = gss_padlen; + memset(padding->buffer.value, (int)gss_padlen, gss_padlen); + } + + if (ctx->gss_flags & GSS_C_DCE_STYLE) + tmsglen = k5_headerlen; /* confounder length */ + else + tmsglen = conf_data_length + padding->buffer.length; + } + + /* Determine token size */ + tlen = g_token_size(ctx->mech_used, 14 + ctx->cksum_size + tmsglen); + + k5_headerlen += tlen - tmsglen; + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(header, k5_headerlen); + else if (header->buffer.length < k5_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + + header->buffer.length = k5_headerlen; + + ptr = (unsigned char *)header->buffer.value; + g_make_token_header(ctx->mech_used, 14 + ctx->cksum_size + tmsglen, &ptr, toktype); + + /* 0..1 SIGN_ALG */ + store_16_le(ctx->signalg, &ptr[0]); + + /* 2..3 SEAL_ALG or Filler */ + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { + store_16_le(ctx->sealalg, &ptr[2]); + } 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 checksum */ + switch (ctx->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_WRAP_MSG) + sign_usage = 15; + break; + default: + case SGN_ALG_DES_MAC: + abort (); + } + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen); + if (code != 0) + goto cleanup; + md5cksum.length = k5_trailerlen; + + if (k5_headerlen != 0) { + code = kg_make_confounder(context, ctx->enc, ptr + 14 + ctx->cksum_size); + if (code != 0) + goto cleanup; + } + + /* compute the checksum */ + code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type, + ctx->cksum_size, ctx->seq, ctx->enc, + sign_usage, iov, iov_count, toktype, + &md5cksum); + if (code != 0) + goto cleanup; + + switch (ctx->signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_3: + 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); + if (code != 0) + goto cleanup; + + cksum.length = ctx->cksum_size; + cksum.contents = md5cksum.contents + 16 - cksum.length; + + memcpy(ptr + 14, cksum.contents, cksum.length); + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + assert(md5cksum.length == ctx->cksum_size); + memcpy(ptr + 14, md5cksum.contents, md5cksum.length); + break; + case SGN_ALG_HMAC_MD5: + memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size); + break; + } + + /* create the seq_num */ + code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF, + (OM_uint32)ctx->seq_send, ptr + 14, ptr + 6); + if (code != 0) + goto cleanup; + + if (conf_req_flag) { + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + size_t i; + + store_32_be(ctx->seq_send, bigend_seqnum); + + code = krb5_copy_keyblock(context, ctx->enc, &enc_key); + if (code != 0) + goto cleanup; + + assert(enc_key->length == 16); + + for (i = 0; i < enc_key->length; i++) + ((char *)enc_key->contents)[i] ^= 0xF0; + + code = kg_arcfour_docrypt_iov(context, enc_key, 0, + bigend_seqnum, 4, + iov, iov_count); + krb5_free_keyblock(context, enc_key); + } else { + code = kg_encrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + 0 /*EC*/, 0 /*RRC*/, + ctx->enc, KG_USAGE_SEAL, NULL, + iov, iov_count); + } + if (code != 0) + goto cleanup; + } + + ctx->seq_send++; + ctx->seq_send &= 0xFFFFFFFFL; + + code = 0; + + if (conf_state != NULL) + *conf_state = conf_req_flag; + +cleanup: + if (code != 0) + kg_release_iov(iov, iov_count); + krb5_free_checksum_contents(context, &md5cksum); + + return code; +} + +OM_uint32 +kg_seal_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_gss_ctx_id_rec *ctx; + krb5_error_code code; + krb5_timestamp now; + krb5_context context; + + if (qop_req != 0) { + *minor_status = (OM_uint32)G_UNKNOWN_QOP; + return GSS_S_FAILURE; + } + + 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; + code = krb5_timeofday(context, &now); + if (code != 0) { + *minor_status = code; + save_error_info(*minor_status, context); + return GSS_S_FAILURE; + } + + if (conf_req_flag && kg_integ_only_iov(iov, iov_count)) { + /* may be more sensible to return an error here */ + conf_req_flag = FALSE; + } + + switch (ctx->proto) { + case 0: + code = make_seal_token_v1_iov(context, ctx, conf_req_flag, + conf_state, iov, iov_count, toktype); + break; + case 1: + code = gss_krb5int_make_seal_token_v3_iov(context, ctx, conf_req_flag, + conf_state, iov, iov_count, toktype); + break; + default: + code = G_UNKNOWN_QOP; + break; + } + + if (code != 0) { + *minor_status = code; + save_error_info(*minor_status, context); + return GSS_S_FAILURE; + } + + *minor_status = 0; + + return (ctx->krb_times.endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; +} + +#define INIT_IOV_DATA(_iov) do { (_iov)->buffer.value = NULL; \ + (_iov)->buffer.length = 0; } \ + while (0) + +OM_uint32 +kg_seal_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + krb5_gss_ctx_id_rec *ctx; + gss_iov_buffer_t header, trailer, padding; + size_t data_length, assoc_data_length; + size_t gss_headerlen, gss_padlen, gss_trailerlen; + unsigned int k5_headerlen = 0, k5_trailerlen = 0, k5_padlen = 0; + krb5_error_code code; + krb5_context context; + int dce_style; + + if (qop_req != GSS_C_QOP_DEFAULT) { + *minor_status = (OM_uint32)G_UNKNOWN_QOP; + return GSS_S_FAILURE; + } + + 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; + } + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + INIT_IOV_DATA(header); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL) { + INIT_IOV_DATA(trailer); + } + + dce_style = ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0); + + /* For CFX, EC is used instead of padding, and is placed in header or trailer */ + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding == NULL) { + if (conf_req_flag && ctx->proto == 0 && !dce_style) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } else { + INIT_IOV_DATA(padding); + } + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + if (conf_req_flag && kg_integ_only_iov(iov, iov_count)) + conf_req_flag = FALSE; + + context = ctx->k5_context; + + gss_headerlen = gss_padlen = gss_trailerlen = 0; + + if (ctx->proto == 1) { + krb5_enctype enctype; + size_t ec; + + if (ctx->have_acceptor_subkey) + enctype = ctx->acceptor_subkey->enctype; + else + enctype = ctx->subkey->enctype; + + code = krb5_c_crypto_length(context, enctype, + conf_req_flag ? + KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (conf_req_flag) { + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + } + + gss_headerlen = 16; /* Header */ + if (conf_req_flag) { + gss_headerlen += k5_headerlen; /* Kerb-Header */ + gss_trailerlen = 16 /* E(Header) */ + k5_trailerlen; /* Kerb-Trailer */ + + code = krb5_c_padding_length(context, enctype, + data_length - assoc_data_length + 16 /* E(Header) */, &k5_padlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (k5_padlen == 0 && dce_style) { + /* Windows rejects AEAD tokens with non-zero EC */ + code = krb5_c_block_size(context, enctype, &ec); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + } else + ec = k5_padlen; + + gss_trailerlen += ec; + } else { + gss_trailerlen = k5_trailerlen; /* Kerb-Checksum */ + } + } else if (!dce_style) { + k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; + + if (k5_padlen == 1) + gss_padlen = 1; + else + gss_padlen = k5_padlen - ((data_length - assoc_data_length) % k5_padlen); + } + + data_length += gss_padlen; + + if (ctx->proto == 0) { + /* Header | Checksum | Confounder | Data | Pad */ + size_t data_size; + + k5_headerlen = kg_confounder_size(context, ctx->enc); + + data_size = 14 /* Header */ + ctx->cksum_size + k5_headerlen; + + if (!dce_style) + data_size += data_length; + + gss_headerlen = g_token_size(ctx->mech_used, data_size); + + /* g_token_size() will include data_size as well as the overhead, so + * subtract data_length just to get the overhead (ie. token size) */ + if (!dce_style) + gss_headerlen -= data_length; + } + + if (minor_status != NULL) + *minor_status = 0; + + if (trailer == NULL) + gss_headerlen += gss_trailerlen; + else + trailer->buffer.length = gss_trailerlen; + + assert(gss_padlen == 0 || padding != NULL); + + if (padding != NULL) + padding->buffer.length = gss_padlen; + + header->buffer.length = gss_headerlen; + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5sealv3.c b/krb5-1-7/src/lib/gssapi/krb5/k5sealv3.c new file mode 100644 index 000000000..26e20d73b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5sealv3.c @@ -0,0 +1,524 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/k5sealv3.c + * + * Copyright 2003,2004,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. + * + * + */ +/* draft-ietf-krb-wg-gssapi-cfx-05 */ + +#include +#include "k5-platform.h" /* for 64-bit support */ +#include "k5-int.h" /* for zap() */ +#include "gssapiP_krb5.h" +#include + +int +gss_krb5int_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 }; + +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; + krb5_cksumtype cksumtype; + + 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; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + +#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, key->enctype); + /* Allocate space for header plus encrypted data. */ + outbuf = malloc(bufsize); + if (outbuf == NULL) { + free(plain.data); + return ENOMEM; + } + + /* TOK_ID */ + store_16_be(KG2_TOK_WRAP_MSG, 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 = (char *)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 (gss_krb5int_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; + size_t cksumsize; + + /* 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 = KG2_TOK_WRAP_MSG; + + wrap_with_checksum: + plain.length = message->length + 16; + plain.data = malloc(message->length + 16); + if (plain.data == NULL) + return ENOMEM; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) + goto error; + + assert(cksumsize <= 0xffff); + + bufsize = 16 + message2->length + cksumsize; + 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 = cksumsize; + + err = krb5_c_make_checksum(context, cksumtype, key, + key_usage, &plain, &sum); + zap(plain.data, plain.length); + free(plain.data); + plain.data = 0; + if (err) { + zap(outbuf,bufsize); + goto error; + } + if (sum.length != cksumsize) + abort(); + memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize); + 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 (gss_krb5int_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(cksumsize, outbuf+4); + } else { + store_16_be(0xffff, outbuf+6); + } + } else if (toktype == KG_TOK_MIC_MSG) { + tok_id = KG2_TOK_MIC_MSG; + message2 = &empty_message; + goto wrap_with_checksum; + } else if (toktype == KG_TOK_DEL_CTX) { + tok_id = KG2_TOK_DEL_CTX; + 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, unsigned int bodysize, + gss_buffer_t message_buffer, + int *conf_state, gss_qop_t *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; + krb5_cksumtype cksumtype; + + if (ctx->big_endian != 0) + goto defective; + + 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 = (OM_uint32)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; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + + if (toktype == KG_TOK_WRAP_MSG) { + if (load_16_be(ptr) != KG2_TOK_WRAP_MSG) + 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 (!gss_krb5int_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 = (char *)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 = (unsigned char *)plain.data + plain.length - 16; + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || 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 { + size_t cksumsize; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) + goto error; + + /* 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 = (char *)ptr; + if (!gss_krb5int_rotate_left(ptr, bodysize-ec, 16)) + goto no_mem; + sum.length = ec; + if (sum.length != cksumsize) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + sum.contents = ptr+bodysize-ec; + sum.checksum_type = 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) != KG2_TOK_MIC_MSG) + 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 = 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; + save_error_info(*minor_status, context); + 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) != KG2_TOK_DEL_CTX) + goto defective; + message_buffer = (gss_buffer_t)&empty_message; + goto verify_mic_1; + } else { + goto defective; + } +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5sealv3iov.c b/krb5-1-7/src/lib/gssapi/krb5/k5sealv3iov.c new file mode 100644 index 000000000..c30352b0a --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5sealv3iov.c @@ -0,0 +1,469 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/k5sealv3iov.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5-platform.h" /* for 64-bit support */ +#include "k5-int.h" /* for zap() */ +#include "gssapiP_krb5.h" +#include + +krb5_error_code +gss_krb5int_make_seal_token_v3_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code = 0; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + unsigned char acceptor_flag; + unsigned short tok_id; + unsigned char *outbuf = NULL; + unsigned char *tbuf = NULL; + int key_usage; + size_t rrc = 0; + unsigned int gss_headerlen, gss_trailerlen; + krb5_keyblock *key; + krb5_cksumtype cksumtype; + size_t data_length, assoc_data_length; + + assert(ctx->big_endian == 0); + assert(ctx->proto == 1); + + 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; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + assert(cksumtype != 0); + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) + return EINVAL; + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL) + padding->buffer.length = 0; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { + unsigned int k5_headerlen, k5_trailerlen, k5_padlen; + size_t ec = 0; + size_t conf_data_length = data_length - assoc_data_length; + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + goto cleanup; + + code = krb5_c_padding_length(context, key->enctype, + conf_data_length + 16 /* E(Header) */, &k5_padlen); + if (code != 0) + goto cleanup; + + if (k5_padlen == 0 && (ctx->gss_flags & GSS_C_DCE_STYLE)) { + /* Windows rejects AEAD tokens with non-zero EC */ + code = krb5_c_block_size(context, key->enctype, &ec); + if (code != 0) + goto cleanup; + } else + ec = k5_padlen; + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen); + if (code != 0) + goto cleanup; + + gss_headerlen = 16 /* Header */ + k5_headerlen; + gss_trailerlen = ec + 16 /* E(Header) */ + k5_trailerlen; + + if (trailer == NULL) { + rrc = gss_trailerlen; + /* Workaround for Windows bug where it rotates by EC + RRC */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) + rrc -= ec; + gss_headerlen += gss_trailerlen; + } + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(header, (size_t) gss_headerlen); + } else if (header->buffer.length < gss_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + outbuf = (unsigned char *)header->buffer.value; + header->buffer.length = (size_t) gss_headerlen; + + if (trailer != NULL) { + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(trailer, (size_t) gss_trailerlen); + else if (trailer->buffer.length < gss_trailerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + trailer->buffer.length = (size_t) gss_trailerlen; + } + + /* TOK_ID */ + store_16_be(KG2_TOK_WRAP_MSG, 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); + + /* EC | copy of header to be encrypted, located in (possibly rotated) trailer */ + if (trailer == NULL) + tbuf = (unsigned char *)header->buffer.value + 16; /* Header */ + else + tbuf = (unsigned char *)trailer->buffer.value; + + memset(tbuf, 0xFF, ec); + memcpy(tbuf + ec, header->buffer.value, 16); + + code = kg_encrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + ec, rrc, key, key_usage, 0, iov, iov_count); + if (code != 0) + goto cleanup; + + /* RRC */ + store_16_be(rrc, outbuf + 6); + + ctx->seq_send++; + } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { + tok_id = KG2_TOK_WRAP_MSG; + + wrap_with_checksum: + + gss_headerlen = 16; + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_CHECKSUM, &gss_trailerlen); + if (code != 0) + goto cleanup; + + assert(gss_trailerlen <= 0xFFFF); + + if (trailer == NULL) { + rrc = gss_trailerlen; + gss_headerlen += gss_trailerlen; + } + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(header, (size_t) gss_headerlen); + else if (header->buffer.length < gss_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + outbuf = (unsigned char *)header->buffer.value; + header->buffer.length = (size_t) gss_headerlen; + + if (trailer != NULL) { + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(trailer, (size_t) gss_trailerlen); + else if (trailer->buffer.length < gss_trailerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + trailer->buffer.length = (size_t) gss_trailerlen; + } + + /* 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); + + code = kg_make_checksum_iov_v3(context, cksumtype, + rrc, key, key_usage, + iov, iov_count); + if (code != 0) + goto cleanup; + + ctx->seq_send++; + + if (toktype == KG_TOK_WRAP_MSG) { + /* Fix up EC field */ + store_16_be(gss_trailerlen, outbuf + 4); + /* Fix up RRC field */ + store_16_be(rrc, outbuf + 6); + } + } else if (toktype == KG_TOK_MIC_MSG) { + tok_id = KG2_TOK_MIC_MSG; + trailer = NULL; + goto wrap_with_checksum; + } else if (toktype == KG_TOK_DEL_CTX) { + tok_id = KG2_TOK_DEL_CTX; + goto wrap_with_checksum; + } else { + abort(); + } + + code = 0; + +cleanup: + if (code != 0) + kg_release_iov(iov, iov_count); + + return code; +} + +OM_uint32 +gss_krb5int_unseal_v3_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + int *conf_state, + gss_qop_t *qop_state, + int toktype) +{ + OM_uint32 code; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + unsigned char acceptor_flag; + unsigned char *ptr = NULL; + int key_usage; + size_t rrc, ec; + size_t data_length, assoc_data_length; + krb5_keyblock *key; + gssint_uint64 seqnum; + krb5_boolean valid; + krb5_cksumtype cksumtype; + int conf_flag = 0; + + if (ctx->big_endian != 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL && padding->buffer.length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + 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)); + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + ptr = (unsigned char *)header->buffer.value; + + if (header->buffer.length < 16) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { + *minor_status = (OM_uint32)G_BAD_DIRECTION; + return GSS_S_BAD_SIG; + } + + if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) { + key = ctx->acceptor_subkey; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + + + if (toktype == KG_TOK_WRAP_MSG) { + unsigned int k5_trailerlen; + + if (load_16_be(ptr) != KG2_TOK_WRAP_MSG) + goto defective; + conf_flag = ((ptr[2] & FLAG_WRAP_CONFIDENTIAL) != 0); + if (ptr[3] != 0xFF) + goto defective; + ec = load_16_be(ptr + 4); + rrc = load_16_be(ptr + 6); + seqnum = load_64_be(ptr + 8); + + code = krb5_c_crypto_length(context, key->enctype, + conf_flag ? KRB5_CRYPTO_TYPE_TRAILER : + KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + /* Deal with RRC */ + if (trailer == NULL) { + size_t desired_rrc = k5_trailerlen; + + if (conf_flag) { + desired_rrc += 16; /* E(Header) */ + + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) + desired_rrc += ec; + } + + /* According to MS, we only need to deal with a fixed RRC for DCE */ + if (rrc != desired_rrc) + goto defective; + } else if (rrc != 0) { + /* Should have been rotated by kg_unseal_stream_iov() */ + goto defective; + } + + if (conf_flag) { + unsigned char *althdr; + + /* Decrypt */ + code = kg_decrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + ec, rrc, + key, key_usage, 0, iov, iov_count); + if (code != 0) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + + /* Validate header integrity */ + if (trailer == NULL) + althdr = (unsigned char *)header->buffer.value + 16 + ec; + else + althdr = (unsigned char *)trailer->buffer.value + ec; + + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] + || memcmp(althdr + 8, ptr + 8, 8) != 0) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + } else { + /* Verify checksum: note EC is checksum size here, not padding */ + if (ec != k5_trailerlen) + goto defective; + + /* Zero EC, RRC before computing checksum */ + store_16_be(0, ptr + 4); + store_16_be(0, ptr + 6); + + code = kg_verify_checksum_iov_v3(context, cksumtype, rrc, + key, key_usage, + iov, iov_count, &valid); + if (code != 0 || valid == FALSE) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + } + + code = g_order_check(&ctx->seqstate, seqnum); + } else if (toktype == KG_TOK_MIC_MSG) { + if (load_16_be(ptr) != KG2_TOK_MIC_MSG) + goto defective; + + verify_mic_1: + if (ptr[3] != 0xFF) + goto defective; + seqnum = load_64_be(ptr + 8); + + code = kg_verify_checksum_iov_v3(context, cksumtype, 0, + key, key_usage, + iov, iov_count, &valid); + if (code != 0 || valid == FALSE) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + code = g_order_check(&ctx->seqstate, seqnum); + } else if (toktype == KG_TOK_DEL_CTX) { + if (load_16_be(ptr) != KG2_TOK_DEL_CTX) + goto defective; + goto verify_mic_1; + } else { + goto defective; + } + + *minor_status = 0; + + if (conf_state != NULL) + *conf_state = conf_flag; + + return code; + +defective: + *minor_status = 0; + + return GSS_S_DEFECTIVE_TOKEN; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5unseal.c b/krb5-1-7/src/lib/gssapi/krb5/k5unseal.c new file mode 100644 index 000000000..f55180af8 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5unseal.c @@ -0,0 +1,561 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2007 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 +#endif +#include + +/* 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) { + size_t tmsglen = bodysize-(14+cksum_len); + if (sealalg != 0xffff) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + int i; + store_32_be(seqnum, bigend_seqnum); + 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->krb_times.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 = (OM_uint32)G_BAD_DIRECTION; + return(GSS_S_BAD_SIG); + } + + retval = g_order_check(&(ctx->seqstate), (gssint_uint64)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; + gss_qop_t *qop_state; + int toktype; +{ + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + unsigned int bodysize; + int err; + int toktype2; + int vfyflags = 0; + OM_uint32 ret; + + /* 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; + + + err = g_verify_token_header(ctx->mech_used, + &bodysize, &ptr, -1, + input_token_buffer->length, + vfyflags); + if (err) { + *minor_status = err; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: + ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx, + ptr, bodysize, message_buffer, + conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, + toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + ret = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (ret != 0) + save_error_info (*minor_status, ctx->k5_context); + + return ret; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/k5unsealiov.c b/krb5-1-7/src/lib/gssapi/krb5/k5unsealiov.c new file mode 100644 index 000000000..5d2bd1afa --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/k5unsealiov.c @@ -0,0 +1,665 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/k5unsealiov.c + * + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5-platform.h" /* for 64-bit support */ +#include "k5-int.h" /* for zap() */ +#include "gssapiP_krb5.h" +#include + +static OM_uint32 +kg_unseal_v1_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + size_t token_wrapper_len, + int *conf_state, + gss_qop_t *qop_state, + int toktype) +{ + OM_uint32 code; + gss_iov_buffer_t header; + gss_iov_buffer_t trailer; + unsigned char *ptr; + int sealalg; + int signalg; + krb5_checksum cksum; + krb5_checksum md5cksum; + krb5_timestamp now; + size_t cksum_len = 0; + size_t conflen = 0; + int direction; + krb5_ui_4 seqnum; + OM_uint32 retval; + size_t sumlen; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + + assert(toktype == KG_TOK_WRAP_MSG); + + md5cksum.length = cksum.length = 0; + md5cksum.contents = cksum.contents = NULL; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL && trailer->buffer.length != 0) { + *minor_status = (OM_uint32)KRB5_BAD_MSIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (header->buffer.length < token_wrapper_len + 14) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + ptr = (unsigned char *)header->buffer.value + token_wrapper_len; + + signalg = ptr[0]; + signalg |= ptr[1] << 8; + + sealalg = ptr[2]; + sealalg |= ptr[3] << 8; + + if (ptr[4] != 0xFF || ptr[5] != 0xFF) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (toktype != KG_TOK_WRAP_MSG && sealalg != 0xFFFF) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (toktype == KG_TOK_WRAP_MSG && + !(sealalg == 0xFFFF || sealalg == ctx->sealalg)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + 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_WRAP_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 */ + code = kg_get_seq_num(context, ctx->seq, ptr + 14, ptr + 6, &direction, + &seqnum); + if (code != 0) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + + assert(ctx->big_endian == 0); + + /* decode the message, if SEAL */ + if (toktype == KG_TOK_WRAP_MSG) { + if (sealalg != 0xFFFF) { + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + size_t i; + + store_32_be(seqnum, bigend_seqnum); + + code = krb5_copy_keyblock(context, ctx->enc, &enc_key); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + + assert(enc_key->length == 16); + + for (i = 0; i < enc_key->length; i++) + ((char *)enc_key->contents)[i] ^= 0xF0; + + code = kg_arcfour_docrypt_iov(context, enc_key, 0, + &bigend_seqnum[0], 4, + iov, iov_count); + krb5_free_keyblock(context, enc_key); + } else { + code = kg_decrypt_iov(context, 0, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + 0 /*EC*/, 0 /*RRC*/, + ctx->enc, KG_USAGE_SEAL, NULL, + iov, iov_count); + } + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + } + conflen = kg_confounder_size(context, ctx->enc); + } + + if (header->buffer.length != token_wrapper_len + 14 + cksum_len + conflen) { + retval = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + /* compute the checksum of the message */ + + /* initialize the checksum */ + + 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 != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + md5cksum.length = sumlen; + + /* compute the checksum of the message */ + code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type, + cksum_len, ctx->seq, ctx->enc, + sign_usage, iov, iov_count, toktype, + &md5cksum); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_3: + 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); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + + cksum.length = cksum_len; + cksum.contents = md5cksum.contents + 16 - cksum.length; + + code = memcmp(cksum.contents, ptr + 14, cksum.length); + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + case SGN_ALG_HMAC_MD5: + code = memcmp(md5cksum.contents, ptr + 14, cksum_len); + break; + default: + code = 0; + retval = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + break; + } + + if (code != 0) { + code = 0; + retval = GSS_S_BAD_SIG; + goto cleanup; + } + + /* + * For GSS_C_DCE_STYLE, the caller manages the padding, because the + * pad length is in the RPC PDU. The value of the padding may be + * uninitialized. For normal GSS, the last bytes of the decrypted + * data contain the pad length. kg_fixup_padding_iov() will find + * this and fixup the last data IOV appropriately. + */ + if (toktype == KG_TOK_WRAP_MSG && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + retval = kg_fixup_padding_iov(&code, iov, iov_count); + if (retval != GSS_S_COMPLETE) + goto cleanup; + } + + if (conf_state != NULL) + *conf_state = (sealalg != 0xFFFF); + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + code = krb5_timeofday(context, &now); + if (code != 0) { + *minor_status = code; + retval = GSS_S_FAILURE; + goto cleanup; + } + + if (now > ctx->krb_times.endtime) { + *minor_status = 0; + retval = GSS_S_CONTEXT_EXPIRED; + goto cleanup; + } + + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + *minor_status = (OM_uint32)G_BAD_DIRECTION; + retval = GSS_S_BAD_SIG; + } + + code = 0; + retval = g_order_check(&ctx->seqstate, (gssint_uint64)seqnum); + +cleanup: + krb5_free_checksum_contents(context, &md5cksum); + + *minor_status = code; + + return retval; +} + +/* + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except + * for DCE in which case it can just provide TOKEN | DATA (must + * guarantee that DATA is padded) + */ +static OM_uint32 +kg_unseal_iov_token(OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code; + krb5_context context = ctx->k5_context; + unsigned char *ptr; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + size_t input_length; + unsigned int bodysize; + int toktype2; + int vfyflags = 0; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + ptr = (unsigned char *)header->buffer.value; + input_length = header->buffer.length; + + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + size_t data_length, assoc_data_length; + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + input_length += data_length - assoc_data_length; + + if (padding != NULL) + input_length += padding->buffer.length; + + if (trailer != NULL) + input_length += trailer->buffer.length; + } + + if (ctx->gss_flags & GSS_C_DCE_STYLE) + vfyflags |= G_VFY_TOKEN_HDR_IGNORE_SEQ_SIZE; + + code = g_verify_token_header(ctx->mech_used, + &bodysize, &ptr, -1, + input_length, 0); + if (code != 0) { + *minor_status = code; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: + code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count, + conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + code = kg_unseal_v1_iov(context, minor_status, ctx, iov, iov_count, + (size_t)(ptr - (unsigned char *)header->buffer.value), + conf_state, qop_state, toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + code = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (code != 0) + save_error_info(*minor_status, context); + + return code; +} + +/* + * Split a STREAM | SIGN_DATA | DATA into + * HEADER | SIGN_DATA | DATA | PADDING | TRAILER + */ +static OM_uint32 +kg_unseal_stream_iov(OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + unsigned char *ptr; + unsigned int bodysize; + OM_uint32 code = 0, major_status = GSS_S_FAILURE; + krb5_context context = ctx->k5_context; + int conf_req_flag, toktype2; + int i = 0, j; + gss_iov_buffer_desc *tiov = NULL; + gss_iov_buffer_t stream, data = NULL; + gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer; + + assert(toktype == KG_TOK_WRAP_MSG); + + if (toktype != KG_TOK_WRAP_MSG || (ctx->gss_flags & GSS_C_DCE_STYLE)) { + code = EINVAL; + goto cleanup; + } + + stream = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM); + assert(stream != NULL); + + ptr = (unsigned char *)stream->buffer.value; + + code = g_verify_token_header(ctx->mech_used, + &bodysize, &ptr, -1, + stream->buffer.length, 0); + if (code != 0) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + tiov = (gss_iov_buffer_desc *)calloc((size_t)iov_count + 2, sizeof(gss_iov_buffer_desc)); + if (tiov == NULL) { + code = ENOMEM; + goto cleanup; + } + + /* HEADER */ + theader = &tiov[i++]; + theader->type = GSS_IOV_BUFFER_TYPE_HEADER; + theader->buffer.value = stream->buffer.value; + theader->buffer.length = ptr - (unsigned char *)stream->buffer.value; + if (bodysize < 14 || + stream->buffer.length != theader->buffer.length + bodysize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + theader->buffer.length += 14; + + /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */ + for (j = 0; j < iov_count; j++) { + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type); + + if (type == GSS_IOV_BUFFER_TYPE_DATA) { + if (data != NULL) { + /* only a single DATA buffer can appear */ + code = EINVAL; + goto cleanup; + } + + data = &iov[j]; + tdata = &tiov[i]; + } + if (type == GSS_IOV_BUFFER_TYPE_DATA || + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + tiov[i++] = iov[j]; + } + + if (data == NULL) { + /* a single DATA buffer must be present */ + code = EINVAL; + goto cleanup; + } + + /* PADDING | TRAILER */ + tpadding = &tiov[i++]; + tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING; + tpadding->buffer.length = 0; + tpadding->buffer.value = NULL; + + ttrailer = &tiov[i++]; + ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: { + size_t ec, rrc; + krb5_enctype enctype = ctx->enc->enctype; + unsigned int k5_headerlen = 0; + unsigned int k5_trailerlen = 0; + + conf_req_flag = ((ptr[0] & FLAG_WRAP_CONFIDENTIAL) != 0); + ec = conf_req_flag ? load_16_be(ptr + 2) : 0; + rrc = load_16_be(ptr + 4); + + if (rrc != 0) { + if (!gss_krb5int_rotate_left((unsigned char *)stream->buffer.value + 16, + stream->buffer.length - 16, rrc)) { + code = ENOMEM; + goto cleanup; + } + store_16_be(0, ptr + 4); /* set RRC to zero */ + } + + if (conf_req_flag) { + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + goto cleanup; + theader->buffer.length += k5_headerlen; /* length validated later */ + } + + /* no PADDING for CFX, EC is used instead */ + code = krb5_c_crypto_length(context, enctype, + conf_req_flag ? KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) + goto cleanup; + + ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + k5_trailerlen; + ttrailer->buffer.value = (unsigned char *)stream->buffer.value + + stream->buffer.length - ttrailer->buffer.length; + break; + } + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + theader->buffer.length += ctx->cksum_size + kg_confounder_size(context, ctx->enc); + + /* + * we can't set the padding accurately until decryption; + * kg_fixup_padding_iov() will take care of this + */ + tpadding->buffer.length = 1; + tpadding->buffer.value = (unsigned char *)stream->buffer.value + stream->buffer.length - 1; + + /* no TRAILER for pre-CFX */ + ttrailer->buffer.length = 0; + ttrailer->buffer.value = NULL; + + break; + default: + code = (OM_uint32)G_BAD_TOK_HEADER; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + break; + } + + /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/ + /* Old: GSS-Header | Conf | Data | Pad | */ + /* CFX: GSS-Header | Kerb-Header | Data | | EC | E(Header) | Kerb-Trailer */ + /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/ + + /* validate lengths */ + if (stream->buffer.length < theader->buffer.length + + tpadding->buffer.length + + ttrailer->buffer.length) + { + code = (OM_uint32)KRB5_BAD_MSIZE; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + /* setup data */ + tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length - + tpadding->buffer.length - theader->buffer.length; + + assert(data != NULL); + + if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(tdata, tdata->buffer.length); + if (code != 0) + goto cleanup; + memcpy(tdata->buffer.value, + (unsigned char *)stream->buffer.value + theader->buffer.length, tdata->buffer.length); + } else + tdata->buffer.value = (unsigned char *)stream->buffer.value + theader->buffer.length; + + assert(i <= iov_count + 2); + + major_status = kg_unseal_iov_token(&code, ctx, conf_state, qop_state, + tiov, i, toktype); + if (major_status == GSS_S_COMPLETE) + *data = *tdata; + else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + OM_uint32 tmp; + + gss_release_buffer(&tmp, &tdata->buffer); + tdata->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + +cleanup: + if (tiov != NULL) + free(tiov); + + *minor_status = code; + + return major_status; +} + +OM_uint32 +kg_unseal_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_gss_ctx_id_rec *ctx; + OM_uint32 code; + + 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 (kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) { + code = kg_unseal_stream_iov(minor_status, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } else { + code = kg_unseal_iov_token(minor_status, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } + + return code; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/krb5_gss_glue.c b/krb5-1-7/src/lib/gssapi/krb5/krb5_gss_glue.c new file mode 100644 index 000000000..f9bf03016 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/krb5_gss_glue.c @@ -0,0 +1,418 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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) 2006-2008, 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. + */ + +/* + * $Id$ + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +gss_krb5_get_tkt_flags( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_flags *ticket_flags) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, + GSS_KRB5_GET_TKT_FLAGS_OID }; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (ticket_flags == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(*ticket_flags)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *ticket_flags = *((krb5_flags *)data_set->elements[0].value); + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_copy_ccache( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + krb5_ccache out_ccache) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_COPY_CCACHE_OID_LENGTH, + GSS_KRB5_COPY_CCACHE_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + if (out_ccache == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + req_buffer.value = out_ccache; + req_buffer.length = sizeof(out_ccache); + + major_status = gssspi_set_cred_option(minor_status, + cred_handle, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +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) +{ + unsigned char oid_buf[GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH + 6]; + gss_OID_desc req_oid; + OM_uint32 major_status, minor; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (kctx == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *kctx = NULL; + + req_oid.elements = oid_buf; + req_oid.length = sizeof(oid_buf); + + major_status = generic_gss_oid_compose(minor_status, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, + (int)version, + &req_oid); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + *context_handle, + &req_oid, + &data_set); + if (GSS_ERROR(major_status)) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(void *)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *kctx = *((void **)data_set->elements[0].value); + + /* 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; + + generic_gss_release_buffer_set(&minor, &data_set); + + return GSS_S_COMPLETE; +} + +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) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID }; + OM_uint32 major_status; + struct krb5_gss_set_allowable_enctypes_req req; + gss_buffer_desc req_buffer; + + req.num_ktypes = num_ktypes; + req.ktypes = ktypes; + + req_buffer.length = sizeof(req); + req_buffer.value = &req; + + major_status = gssspi_set_cred_option(minor_status, + cred, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_ccache_name( + OM_uint32 *minor_status, + const char *name, + const char **out_name) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_CCACHE_NAME_OID_LENGTH, + GSS_KRB5_CCACHE_NAME_OID }; + OM_uint32 major_status; + struct krb5_gss_ccache_name_req req; + gss_buffer_desc req_buffer; + + req.name = name; + req.out_name = out_name; + + req_buffer.length = sizeof(req); + req_buffer.value = &req; + + major_status = gssspi_mech_invoke(minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_free_lucid_sec_context( + OM_uint32 *minor_status, + void *kctx) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, + GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + req_buffer.length = sizeof(kctx); + req_buffer.value = kctx; + + major_status = gssspi_mech_invoke(minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_register_acceptor_identity(const char *keytab) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID }; + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc req_buffer; + + req_buffer.length = strlen(keytab); + req_buffer.value = (char *)keytab; + + major_status = gssspi_mech_invoke(&minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +krb5_error_code +krb5_gss_use_kdc_context(void) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, + GSS_KRB5_USE_KDC_CONTEXT_OID }; + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc req_buffer; + krb5_error_code ret; + + req_buffer.length = 0; + req_buffer.value = NULL; + + major_status = gssspi_mech_invoke(&minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + if (major_status != GSS_S_COMPLETE) { + if (minor_status != 0) + ret = (krb5_error_code)minor_status; + else + ret = KRB5KRB_ERR_GENERIC; + } else + ret = 0; + + return ret; +} + +/* + * This API should go away and be replaced with an accessor + * into a gss_name_t. + */ +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authz_data_from_sec_context( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data) +{ + gss_OID_desc req_oid; + unsigned char oid_buf[GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH + 6]; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (ad_data == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + req_oid.elements = oid_buf; + req_oid.length = sizeof(oid_buf); + + major_status = generic_gss_oid_compose(minor_status, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, + ad_type, + &req_oid); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1) { + return GSS_S_FAILURE; + } + + ad_data->length = data_set->elements[0].length; + ad_data->value = data_set->elements[0].value; + + data_set->elements[0].length = 0; + data_set->elements[0].value = NULL; + + data_set->count = 0; + + gss_release_buffer_set(minor_status, &data_set); + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_set_cred_rcache( + OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_rcache rcache) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, + GSS_KRB5_SET_CRED_RCACHE_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + req_buffer.length = sizeof(rcache); + req_buffer.value = rcache; + + major_status = gssspi_set_cred_option(minor_status, + cred, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_timestamp *authtime) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, + GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID }; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (authtime == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(*authtime)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *authtime = *((krb5_timestamp *)data_set->elements[0].value); + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/lucid_context.c b/krb5-1-7/src/lib/gssapi/krb5/lucid_context.c new file mode 100644 index 000000000..cefac261e --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/lucid_context.c @@ -0,0 +1,303 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/lucid_context.c + * + * Copyright 2004, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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, + 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, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_error_code kret = 0; + OM_uint32 retval; + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + void *lctx = NULL; + int version = 0; + gss_buffer_desc rep; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + retval = generic_gss_oid_decompose(minor_status, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, + desired_object, + &version); + if (GSS_ERROR(retval)) + return retval; + + /* 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; + } + + rep.value = &lctx; + rep.length = sizeof(lctx); + + retval = generic_gss_add_buffer_set_member(minor_status, &rep, data_set); + if (GSS_ERROR(retval)) + goto error_out; + +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 +gss_krb5int_free_lucid_sec_context( + OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 retval; + krb5_error_code kret = 0; + int version; + void *kctx; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + + kctx = value->value; + 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: + (void)kg_delete_lucidctx_id(kctx); + free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx); + break; + default: + kret = EINVAL; + break; + } + + if (kret) + goto error_out; + + /* Success! */ + *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, + 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->krb_times.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->seq, + &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->acceptor_subkey, + &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-7/src/lib/gssapi/krb5/process_context_token.c b/krb5-1-7/src/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 000000000..9a4d282ac --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,65 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/gssapi/krb5/rel_cred.c b/krb5-1-7/src/lib/gssapi/krb5/rel_cred.c new file mode 100644 index 000000000..833054326 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/rel_cred.c @@ -0,0 +1,96 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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; + +#ifndef LEAN_CLIENT + if (cred->keytab) + code2 = krb5_kt_close(context, cred->keytab); + else +#endif /* LEAN_CLIENT */ + 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); + + *cred_handle = NULL; + + *minor_status = 0; + if (code1) + *minor_status = code1; + if (code2) + *minor_status = code2; + if (code3) + *minor_status = code3; + + if (*minor_status) + save_error_info(*minor_status, context); + krb5_free_context(context); + return(*minor_status?GSS_S_FAILURE:GSS_S_COMPLETE); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/rel_name.c b/krb5-1-7/src/lib/gssapi/krb5/rel_name.c new file mode 100644 index 000000000..49d194448 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/rel_name.c @@ -0,0 +1,55 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/gssapi/krb5/rel_oid.c b/krb5-1-7/src/lib/gssapi/krb5/rel_oid.c new file mode 100644 index 000000000..7a08da2be --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/rel_oid.c @@ -0,0 +1,86 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/rel_oid.c + * + * Copyright 1995, 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. + * + */ + +/* + * 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. + */ + + *minor_status = 0; + 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; + return(GSS_S_COMPLETE); + } +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/seal.c b/krb5-1-7/src/lib/gssapi/krb5/seal.c new file mode 100644 index 000000000..d84e2eecf --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/seal.c @@ -0,0 +1,82 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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$ + */ + +/* 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, + qop_req, input_message_buffer, conf_state, + output_message_buffer, KG_TOK_WRAP_MSG)); +} + +/* AEAD interfaces */ +OM_uint32 +krb5_gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov(minor_status, context_handle, conf_req_flag, + qop_req, conf_state, + iov, iov_count, KG_TOK_WRAP_MSG); + + return major_status; +} + +OM_uint32 +krb5_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov_length(minor_status, context_handle, conf_req_flag, + qop_req, conf_state, iov, iov_count); + return major_status; +} + diff --git a/krb5-1-7/src/lib/gssapi/krb5/ser_sctx.c b/krb5-1-7/src/lib/gssapi/krb5/ser_sctx.c new file mode 100644 index 000000000..60ea9058c --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/ser_sctx.c @@ -0,0 +1,747 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/gssapi/krb5/ser_sctx.c + * + * Copyright 1995, 2004, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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((size_t)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 authtime. + * krb5_int32 for starttime. + * krb5_int32 for endtime. + * krb5_int32 for renew_till. + * 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 number of elements in authdata array + * ... for authdata array + * krb5_int32 for trailer. + */ + kret = EINVAL; + if ((ctx = (krb5_gss_ctx_id_rec *) arg)) { + required = 21*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 && ctx->authdata) { + krb5_int32 i; + + for (i = 0; !kret && ctx->authdata[i]; i++) { + kret = krb5_size_opaque(kcontext, + KV5M_AUTHDATA, + (krb5_pointer)ctx->authdata[i], + &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->krb_times.authtime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.starttime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.endtime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.renew_till, + &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); + if (!kret) { + krb5_int32 i = 0; + + if (ctx->authdata) { + for (; ctx->authdata[i]; i++) + ; + } + /* authdata count */ + kret = krb5_ser_pack_int32(i, &bp, &remain); + if (!kret && ctx->authdata) { + /* authdata */ + for (i = 0; !kret && ctx->authdata[i]; i++) + kret = krb5_externalize_opaque(kcontext, + KV5M_AUTHDATA, + ctx->authdata[i], + &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->krb_times.authtime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.starttime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.endtime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.renew_till = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_flags = (krb5_flags) ibuf; + (void) (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_send, &bp, &remain); + kret = (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_recv, &bp, &remain); + if (kret) { + free(ctx); + return kret; + } + + { + krb5_pointer tmp; + kret = kg_oid_internalize(kcontext, &tmp, &bp, + &remain); + if (kret == 0) + ctx->mech_used = tmp; + else 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->acceptor_subkey_cksumtype = ibuf; + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->cred_rcache = ibuf; + /* authdata */ + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret) { + krb5_int32 nadata = ibuf, i; + + if (nadata > 0) { + ctx->authdata = (krb5_authdata **)calloc((size_t)nadata + 1, + sizeof(krb5_authdata *)); + if (ctx->authdata == NULL) { + kret = ENOMEM; + } else { + for (i = 0; !kret && i < nadata; i++) + kret = krb5_internalize_opaque(kcontext, + KV5M_AUTHDATA, + (krb5_pointer *)&ctx->authdata[i], + &bp, + &remain); + } + } + } + /* 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-7/src/lib/gssapi/krb5/set_allowable_enctypes.c b/krb5-1-7/src/lib/gssapi/krb5/set_allowable_enctypes.c new file mode 100644 index 000000000..5cc72df8b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/set_allowable_enctypes.c @@ -0,0 +1,138 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#else +#include +#endif +#include "gssapi_krb5.h" + +OM_uint32 KRB5_CALLCONV +gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + unsigned 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; + struct krb5_gss_set_allowable_enctypes_req *req; + + /* Assume a failure */ + *minor_status = 0; + major_status = GSS_S_FAILURE; + + assert(value->length == sizeof(*req)); + req = (struct krb5_gss_set_allowable_enctypes_req *)value->value; + + /* 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 (req->ktypes) { + for (i = 0; i < req->num_ktypes && req->ktypes[i]; i++) { + if (!krb5_c_valid_enctype(req->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, req->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-7/src/lib/gssapi/krb5/set_ccache.c b/krb5-1-7/src/lib/gssapi/krb5/set_ccache.c new file mode 100644 index 000000000..273182637 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/set_ccache.c @@ -0,0 +1,100 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +gss_krb5int_ccache_name(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + char *old_name = NULL; + OM_uint32 err = 0; + OM_uint32 minor = 0; + char *gss_out_name; + struct krb5_gss_ccache_name_req *req; + + err = gss_krb5int_initialize_library(); + if (err) { + *minor_status = err; + return GSS_S_FAILURE; + } + + assert(value->length == sizeof(*req)); + + if (value->length != sizeof(*req)) + return GSS_S_FAILURE; + + req = (struct krb5_gss_ccache_name_req *)value->value; + + gss_out_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME); + + if (req->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 = (char *)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, req->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 (req->out_name) { + *(req->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-7/src/lib/gssapi/krb5/sign.c b/krb5-1-7/src/lib/gssapi/krb5/sign.c new file mode 100644 index 000000000..069768c74 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/sign.c @@ -0,0 +1,77 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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$ + */ + +/* 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, + qop_req, message_buffer, NULL, + message_token, KG_TOK_MIC_MSG)); +} + +#if 0 +OM_uint32 +krb5_gss_get_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov(minor_status, context_handle, FALSE, + qop_req, NULL, + iov, iov_count, KG_TOK_MIC_MSG); + + return major_status; +} + +OM_uint32 +krb5_gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov_length(minor_status, context_handle, conf_req_flag, + qop_req, conf_state, iov, iov_count); + return major_status; +} +#endif diff --git a/krb5-1-7/src/lib/gssapi/krb5/unseal.c b/krb5-1-7/src/lib/gssapi/krb5/unseal.c new file mode 100644 index 000000000..5366effc1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/unseal.c @@ -0,0 +1,67 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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$ + */ + +/* 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; + + rstat = kg_unseal(minor_status, context_handle, + input_message_buffer, output_message_buffer, + conf_state, qop_state, KG_TOK_WRAP_MSG); + return(rstat); +} + +/* AEAD interface */ +OM_uint32 +krb5_gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_unseal_iov(minor_status, context_handle, + conf_state, qop_state, + iov, iov_count, KG_TOK_WRAP_MSG); + + return major_status; +} + diff --git a/krb5-1-7/src/lib/gssapi/krb5/util_cksum.c b/krb5-1-7/src/lib/gssapi/krb5/util_cksum.c new file mode 100644 index 000000000..fc6c849c9 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/util_cksum.c @@ -0,0 +1,295 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#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; +} + +krb5_error_code +kg_make_checksum_iov_v1(krb5_context context, + krb5_cksumtype type, + size_t cksum_len, + krb5_keyblock *seq, + krb5_keyblock *enc, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_checksum *checksum) +{ + krb5_error_code code; + gss_iov_buffer_desc *header; + krb5_crypto_iov *kiov; + size_t kiov_count; + int i = 0, j; + size_t conf_len = 0, token_header_len; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + kiov_count = 3 + iov_count; + kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* Checksum over ( Header | Confounder | Data | Pad ) */ + if (toktype == KG_TOK_WRAP_MSG) + conf_len = kg_confounder_size(context, (krb5_keyblock *)enc); + + /* Checksum output */ + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + kiov[i].data.length = checksum->length; + kiov[i].data.data = xmalloc(checksum->length); + if (kiov[i].data.data == NULL) { + xfree(kiov); + return ENOMEM; + } + i++; + + /* Header | SND_SEQ | SGN_CKSUM | Confounder */ + token_header_len = 16 + cksum_len + conf_len; + + /* Header (calculate from end because of variable length ASN.1 header) */ + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 8; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - token_header_len; + i++; + + /* Confounder */ + if (toktype == KG_TOK_WRAP_MSG) { + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = conf_len; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len; + i++; + } + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + code = krb5_c_make_checksum_iov(context, type, seq, sign_usage, kiov, kiov_count); + if (code == 0) { + checksum->length = kiov[0].data.length; + checksum->contents = (unsigned char *)kiov[0].data.data; + } else + free(kiov[0].data.data); + + xfree(kiov); + + return code; +} + +static krb5_error_code +checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + krb5_boolean verify, + krb5_boolean *valid) +{ + krb5_error_code code; + gss_iov_buffer_desc *header; + gss_iov_buffer_desc *trailer; + krb5_crypto_iov *kiov; + size_t kiov_count; + int i = 0, j; + unsigned int k5_checksumlen; + + if (verify) + *valid = FALSE; + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen); + if (code != 0) + return code; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(rrc != 0 || trailer != NULL); + + if (trailer == NULL) { + if (rrc != k5_checksumlen) + return KRB5_BAD_MSIZE; + if (header->buffer.length != 16 + k5_checksumlen) + return KRB5_BAD_MSIZE; + } else if (trailer->buffer.length != k5_checksumlen) + return KRB5_BAD_MSIZE; + + kiov_count = 2 + iov_count; + kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* Checksum over ( Data | Header ) */ + + /* Data */ + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + /* Header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 16; + kiov[i].data.data = (char *)header->buffer.value; + i++; + + /* Checksum */ + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + if (trailer == NULL) { + kiov[i].data.length = header->buffer.length - 16; + kiov[i].data.data = (char *)header->buffer.value + 16; + } else { + kiov[i].data.length = trailer->buffer.length; + kiov[i].data.data = (char *)trailer->buffer.value; + } + i++; + + if (verify) + code = krb5_c_verify_checksum_iov(context, type, key, sign_usage, kiov, kiov_count, valid); + else + code = krb5_c_make_checksum_iov(context, type, key, sign_usage, kiov, kiov_count); + + xfree(kiov); + + return code; +} + +krb5_error_code +kg_make_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count) +{ + return checksum_iov_v3(context, type, rrc, key, + sign_usage, iov, iov_count, 0, NULL); +} + +krb5_error_code +kg_verify_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + krb5_boolean *valid) +{ + return checksum_iov_v3(context, type, rrc, key, + sign_usage, iov, iov_count, 1, valid); +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/util_crypt.c b/krb5-1-7/src/lib/gssapi/krb5/util_crypt.c new file mode 100644 index 000000000..a8558a594 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/util_crypt.c @@ -0,0 +1,943 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2008 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 +#endif + +const char const kg_arcfour_l40[] = "fortybits"; + +static krb5_error_code +kg_copy_keys(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + krb5_keyblock *subkey) +{ + krb5_error_code code; + + if (ctx->enc != NULL) { + krb5_free_keyblock(context, ctx->enc); + ctx->enc = NULL; + } + + code = krb5_copy_keyblock(context, subkey, &ctx->enc); + if (code != 0) + return code; + + if (ctx->seq != NULL) { + krb5_free_keyblock(context, ctx->seq); + ctx->seq = NULL; + } + + code = krb5_copy_keyblock(context, subkey, &ctx->seq); + if (code != 0) + return code; + + return 0; +} + +krb5_error_code +kg_setup_keys(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + krb5_keyblock *subkey, + krb5_cksumtype *cksumtype) +{ + krb5_error_code code; + unsigned int i; + krb5int_access kaccess; + + assert(ctx != NULL); + assert(subkey != NULL); + + *cksumtype = 0; + ctx->proto = 0; + + if (ctx->enc == NULL) { + ctx->signalg = -1; + ctx->sealalg = -1; + } + + code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION); + if (code != 0) + return code; + + code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype, + cksumtype); + if (code != 0) + return code; + + switch (subkey->enctype) { + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_CRC: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + + ctx->enc->enctype = ENCTYPE_DES_CBC_RAW; + ctx->seq->enctype = ENCTYPE_DES_CBC_RAW; + ctx->signalg = SGN_ALG_DES_MAC_MD5; + ctx->cksum_size = 8; + ctx->sealalg = SEAL_ALG_DES; + + for (i = 0; i < ctx->enc->length; i++) + /*SUPPRESS 113*/ + ctx->enc->contents[i] ^= 0xF0; + break; + case ENCTYPE_DES3_CBC_SHA1: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + + ctx->enc->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->seq->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; + break; + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + + ctx->signalg = SGN_ALG_HMAC_MD5; + ctx->cksum_size = 8; + ctx->sealalg = SEAL_ALG_MICROSOFT_RC4; + break; + default: + ctx->proto = 1; + break; + } + + return 0; +} + +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 || + key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + 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; +{ + int confsize; + krb5_data lrandom; + + confsize = kg_confounder_size(context, key); + if (confsize < 0) + return KRB5_BAD_MSIZE; + + lrandom.length = confsize; + lrandom.data = (char *)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 = (char *)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 = (char *)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[14]; + size_t i = 0; + int exportable = (longterm_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP); + + 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; + + if (exportable) { + memcpy(t, kg_arcfour_l40, sizeof(kg_arcfour_l40)); + i += sizeof(kg_arcfour_l40); + } + store_32_le(ms_usage, &t[i]); + i += 4; + input.data = (void *) &t; + input.length = i; + 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; + if (exportable) + memset(usage_key.contents + 7, 0xab, 9); + + 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); +} + +/* AEAD */ +static krb5_error_code +kg_translate_iov_v1(context, key, iov, iov_count, pkiov, pkiov_count) + krb5_context context; + const krb5_keyblock *key; + gss_iov_buffer_desc *iov; + int iov_count; + krb5_crypto_iov **pkiov; + size_t *pkiov_count; +{ + gss_iov_buffer_desc *header; + gss_iov_buffer_desc *trailer; + int i = 0, j; + size_t kiov_count; + krb5_crypto_iov *kiov; + size_t conf_len; + + *pkiov = NULL; + *pkiov_count = 0; + + conf_len = kg_confounder_size(context, (krb5_keyblock *)key); + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + if (header->buffer.length < conf_len) + return KRB5_BAD_MSIZE; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(trailer == NULL || trailer->buffer.length == 0); + + kiov_count = 3 + iov_count; + kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* For pre-CFX (raw enctypes) there is no krb5 header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER; + kiov[i].data.length = 0; + kiov[i].data.data = NULL; + i++; + + /* For pre-CFX, the confounder is at the end of the GSS header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = conf_len; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len; + i++; + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY) + continue; + + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + kiov[i].data.length = 0; + kiov[i].data.data = NULL; + i++; + + *pkiov = kiov; + *pkiov_count = i; + + return 0; +} + +static krb5_error_code +kg_translate_iov_v3(context, dce_style, ec, rrc, key, iov, iov_count, pkiov, pkiov_count) + krb5_context context; + int dce_style; /* DCE_STYLE indicates actual RRC is EC + RRC */ + size_t ec; /* Extra rotate count for DCE_STYLE, pad length otherwise */ + size_t rrc; /* Rotate count */ + const krb5_keyblock *key; + gss_iov_buffer_desc *iov; + int iov_count; + krb5_crypto_iov **pkiov; + size_t *pkiov_count; +{ + gss_iov_buffer_t header; + gss_iov_buffer_t trailer; + int i = 0, j; + size_t kiov_count; + krb5_crypto_iov *kiov; + unsigned int k5_headerlen = 0, k5_trailerlen = 0; + size_t gss_headerlen, gss_trailerlen; + krb5_error_code code; + + *pkiov = NULL; + *pkiov_count = 0; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(trailer == NULL || rrc == 0); + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + return code; + + code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen); + if (code != 0) + return code; + + /* Check header and trailer sizes */ + gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */ + gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */ + + /* If we're caller without a trailer, we must rotate by trailer length */ + if (trailer == NULL) { + size_t actual_rrc = rrc; + + if (dce_style) + actual_rrc += ec; /* compensate for Windows bug */ + + if (actual_rrc != gss_trailerlen) + return KRB5_BAD_MSIZE; + + gss_headerlen += gss_trailerlen; + gss_trailerlen = 0; + } else { + if (trailer->buffer.length != gss_trailerlen) + return KRB5_BAD_MSIZE; + } + + if (header->buffer.length != gss_headerlen) + return KRB5_BAD_MSIZE; + + kiov_count = 3 + iov_count; + kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* + * The krb5 header is located at the end of the GSS header. + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER; + kiov[i].data.length = k5_headerlen; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen; + i++; + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY) + continue; + + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + /* + * The EC and encrypted GSS header are placed in the trailer, which may + * be rotated directly after the plaintext header if no trailer buffer + * is provided. + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = ec + 16; /* E(Header) */ + if (trailer == NULL) + kiov[i].data.data = (char *)header->buffer.value + 16; + else + kiov[i].data.data = (char *)trailer->buffer.value; + i++; + + /* + * The krb5 trailer is placed after the encrypted copy of the + * krb5 header (which may be in the GSS header or trailer). + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + kiov[i].data.length = k5_trailerlen; + kiov[i].data.data = kiov[i - 1].data.data + ec + 16; /* E(Header) */ + i++; + + *pkiov = kiov; + *pkiov_count = i; + + return 0; +} + +static krb5_error_code +kg_translate_iov(context, proto, dce_style, ec, rrc, key, iov, iov_count, pkiov, pkiov_count) + krb5_context context; + int proto; /* 1 if CFX, 0 for pre-CFX */ + int dce_style; + size_t ec; + size_t rrc; + const krb5_keyblock *key; + gss_iov_buffer_desc *iov; + int iov_count; + krb5_crypto_iov **pkiov; + size_t *pkiov_count; +{ + return proto ? + kg_translate_iov_v3(context, dce_style, ec, rrc, key, iov, iov_count, pkiov, pkiov_count) : + kg_translate_iov_v1(context, key, iov, iov_count, pkiov, pkiov_count); +} + +krb5_error_code +kg_encrypt_iov(context, proto, dce_style, ec, rrc, key, usage, iv, iov, iov_count) + krb5_context context; + int proto; + int dce_style; + size_t ec; + size_t rrc; + krb5_keyblock *key; + int usage; + krb5_pointer iv; + gss_iov_buffer_desc *iov; + int iov_count; +{ + krb5_error_code code; + size_t blocksize; + krb5_data ivd, *pivd; + size_t kiov_count; + krb5_crypto_iov *kiov; + + 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; + } + + code = kg_translate_iov(context, proto, dce_style, ec, rrc, key, + iov, iov_count, &kiov, &kiov_count); + if (code == 0) { + code = krb5_c_encrypt_iov(context, key, usage, pivd, kiov, kiov_count); + free(kiov); + } + + if (pivd != NULL) + free(pivd->data); + + return code; +} + +/* length is the length of the cleartext. */ + +krb5_error_code +kg_decrypt_iov(context, proto, dce_style, ec, rrc, key, usage, iv, iov, iov_count) + krb5_context context; + int proto; + int dce_style; + size_t ec; + size_t rrc; + krb5_keyblock *key; + int usage; + krb5_pointer iv; + gss_iov_buffer_desc *iov; + int iov_count; +{ + krb5_error_code code; + size_t blocksize; + krb5_data ivd, *pivd; + size_t kiov_count; + krb5_crypto_iov *kiov; + + 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; + } + + code = kg_translate_iov(context, proto, dce_style, ec, rrc, key, + iov, iov_count, &kiov, &kiov_count); + if (code == 0) { + code = krb5_c_decrypt_iov(context, key, usage, pivd, kiov, kiov_count); + free(kiov); + } + + if (pivd != NULL) + free(pivd->data); + + return code; +} + +krb5_error_code +kg_arcfour_docrypt_iov (krb5_context context, + const krb5_keyblock *longterm_key , int ms_usage, + const unsigned char *kd_data, size_t kd_data_len, + gss_iov_buffer_desc *iov, int iov_count) +{ + krb5_error_code code; + krb5_data input, output; + krb5int_access kaccess; + krb5_keyblock seq_enc_key, usage_key; + unsigned char t[14]; + size_t i = 0; + int exportable = (longterm_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP); + krb5_crypto_iov *kiov = NULL; + size_t kiov_count = 0; + + 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; + + if (exportable) { + memcpy(t, kg_arcfour_l40, sizeof(kg_arcfour_l40)); + i += sizeof(kg_arcfour_l40); + } + store_32_le(ms_usage, &t[i]); + i += 4; + input.data = (void *) &t; + input.length = i; + 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; + if (exportable) + memset(usage_key.contents + 7, 0xab, 9); + + 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; + + code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */, + 0 /* ec */, 0 /* rrc */, longterm_key, + iov, iov_count, &kiov, &kiov_count); + if (code) + goto cleanup_arcfour; + + code = ((*kaccess.arcfour_enc_provider->encrypt_iov)( + &seq_enc_key, 0, + kiov, kiov_count)); +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); + if (kiov != NULL) + free(kiov); + return (code); +} + +krb5_cryptotype +kg_translate_flag_iov(OM_uint32 type) +{ + krb5_cryptotype ktype; + + switch (GSS_IOV_BUFFER_TYPE(type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + ktype = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + ktype = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + ktype = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + + return ktype; +} + +gss_iov_buffer_t +kg_locate_iov(gss_iov_buffer_desc *iov, + int iov_count, + OM_uint32 type) +{ + int i; + gss_iov_buffer_t p = GSS_C_NO_IOV_BUFFER; + + if (iov == GSS_C_NO_IOV_BUFFER) + return GSS_C_NO_IOV_BUFFER; + + for (i = iov_count - 1; i >= 0; i--) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == type) { + if (p == GSS_C_NO_IOV_BUFFER) + p = &iov[i]; + else + return GSS_C_NO_IOV_BUFFER; + } + } + + return p; +} + +void +kg_iov_msglen(gss_iov_buffer_desc *iov, + int iov_count, + size_t *data_length_p, + size_t *assoc_data_length_p) +{ + int i; + size_t data_length = 0, assoc_data_length = 0; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + *data_length_p = *assoc_data_length_p = 0; + + for (i = 0; i < iov_count; i++) { + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[i].type); + + if (type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + assoc_data_length += iov[i].buffer.length; + + if (type == GSS_IOV_BUFFER_TYPE_DATA || + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + data_length += iov[i].buffer.length; + } + + *data_length_p = data_length; + *assoc_data_length_p = assoc_data_length; +} + +void +kg_release_iov(gss_iov_buffer_desc *iov, int iov_count) +{ + int i; + OM_uint32 min_stat; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + for (i = 0; i < iov_count; i++) { + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + gss_release_buffer(&min_stat, &iov[i].buffer); + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } +} + +OM_uint32 +kg_fixup_padding_iov(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count) +{ + gss_iov_buffer_t padding = NULL; + gss_iov_buffer_t data = NULL; + size_t padlength, relative_padlength; + unsigned char *p; + OM_uint32 minor; + + data = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_DATA); + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + + if (data == NULL) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + + if (padding == NULL || padding->buffer.length == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + p = (unsigned char *)padding->buffer.value; + padlength = p[padding->buffer.length - 1]; + + if (data->buffer.length + padding->buffer.length < padlength || + padlength == 0) { + *minor_status = (OM_uint32)KRB5_BAD_MSIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * kg_unseal_stream_iov() will place one byte of padding in the + * padding buffer; its true value is unknown until after decryption. + * + * relative_padlength contains the number of bytes to compensate the + * padding and data buffers by; it will be zero if the caller manages + * the padding length. + * + * If the caller manages the padding length, then relative_padlength + * wil be zero. + * + * eg. if the buffers are structured as follows: + * + * +---DATA---+-PAD-+ + * | ABCDE444 | 4 | + * +----------+-----+ + * + * after compensation they would look like: + * + * +-DATA--+-PAD--+ + * | ABCDE | NULL | + * +-------+------+ + */ + relative_padlength = padlength - padding->buffer.length; + + assert(data->buffer.length >= relative_padlength); + + data->buffer.length -= relative_padlength; + + if (padding->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + gss_release_buffer(&minor, &padding->buffer); + padding->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + + padding->buffer.length = 0; + padding->buffer.value = NULL; + + return GSS_S_COMPLETE; +} + +int kg_map_toktype(int proto, int toktype) +{ + int toktype2; + + if (proto) + switch (toktype) { + case KG_TOK_SIGN_MSG: + toktype2 = KG2_TOK_MIC_MSG; + break; + case KG_TOK_WRAP_MSG: + toktype2 = KG2_TOK_WRAP_MSG; + break; + case KG_TOK_DEL_CTX: + toktype2 = KG2_TOK_DEL_CTX; + break; + default: + toktype2 = toktype; + break; + } + else + toktype2 = toktype; + + return toktype2; +} + +krb5_boolean kg_integ_only_iov(gss_iov_buffer_desc *iov, int iov_count) +{ + int i; + krb5_boolean has_conf_data = FALSE; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) { + has_conf_data = TRUE; + break; + } + } + + return (has_conf_data == FALSE); +} + +krb5_error_code kg_allocate_iov(gss_iov_buffer_t iov, size_t size) +{ + assert(iov != GSS_C_NO_IOV_BUFFER); + assert(iov->type & GSS_IOV_BUFFER_FLAG_ALLOCATE); + + iov->buffer.length = size; + iov->buffer.value = xmalloc(size); + if (iov->buffer.value == NULL) { + iov->buffer.length = 0; + return ENOMEM; + } + + iov->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED; + + return 0; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/util_seed.c b/krb5-1-7/src/lib/gssapi/krb5/util_seed.c new file mode 100644 index 000000000..b559f5e08 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/util_seed.c @@ -0,0 +1,55 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 +#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; + unsigned int i; + + code = krb5_copy_keyblock(context, key, &tmpkey); + if (code) + return(code); + + /* reverse the key bytes, as per spec */ + + for (i=0; ilength; 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-7/src/lib/gssapi/krb5/util_seqnum.c b/krb5-1-7/src/lib/gssapi/krb5/util_seqnum.c new file mode 100644 index 000000000..b91dd658c --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/util_seqnum.c @@ -0,0 +1,102 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2009 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 || + key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + /* Yes, Microsoft used big-endian sequence number.*/ + store_32_be(seqnum, plain); + return kg_arcfour_docrypt (key, 0, + cksum, 8, + &plain[0], 8, + buf); + + } + + store_32_le(seqnum, plain); + 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 || + key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + 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 || + key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + *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-7/src/lib/gssapi/krb5/val_cred.c b/krb5-1-7/src/lib/gssapi/krb5/val_cred.c new file mode 100644 index 000000000..dd82d5341 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/val_cred.c @@ -0,0 +1,96 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 1997, 2007 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); + } + save_error_info(*minor_status, context); + krb5_free_context(context); + return maj; +} diff --git a/krb5-1-7/src/lib/gssapi/krb5/verify.c b/krb5-1-7/src/lib/gssapi/krb5/verify.c new file mode 100644 index 000000000..033a489b7 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/verify.c @@ -0,0 +1,65 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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$ + */ + +/* 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; + + rstat = kg_unseal(minor_status, context_handle, + token_buffer, message_buffer, + NULL, qop_state, KG_TOK_MIC_MSG); + return(rstat); +} + +#if 0 +OM_uint32 +krb5_gss_verify_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_unseal_iov(minor_status, context_handle, + NULL, qop_state, + iov, iov_count, KG_TOK_WRAP_MSG); + + return major_status; +} +#endif diff --git a/krb5-1-7/src/lib/gssapi/krb5/wrap_size_limit.c b/krb5-1-7/src/lib/gssapi/krb5/wrap_size_limit.c new file mode 100644 index 000000000..7fa9c44d6 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/krb5/wrap_size_limit.c @@ -0,0 +1,183 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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) { + krb5_enctype enctype; + + enctype = ctx->have_acceptor_subkey ? ctx->acceptor_subkey->enctype + : ctx->subkey->enctype; + + while (sz > 0 && krb5_encrypt_size(sz, 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 { + krb5_cksumtype cksumtype; + krb5_error_code err; + size_t cksumsize; + + cksumtype = ctx->have_acceptor_subkey ? ctx->acceptor_subkey_cksumtype + : ctx->cksumtype; + + err = krb5_c_checksum_length(ctx->k5_context, cksumtype, &cksumsize); + if (err) { + *minor_status = err; + return GSS_S_FAILURE; + } + + /* Allow for token header and checksum. */ + if (sz < 16 + cksumsize) + sz = 0; + else + sz -= (16 + cksumsize); + } + + *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-7/src/lib/gssapi/libgssapi_krb5.exports b/krb5-1-7/src/lib/gssapi/libgssapi_krb5.exports new file mode 100644 index 000000000..69f390e45 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/libgssapi_krb5.exports @@ -0,0 +1,92 @@ +GSS_C_INQ_SSPI_SESSION_KEY +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_buffer_set_member +gss_add_cred +gss_add_oid_set_member +gss_canonicalize_name +gss_compare_name +gss_complete_auth_token +gss_context_time +gss_create_empty_buffer_set +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_cred_by_oid +gss_inquire_mechs_for_name +gss_inquire_names_for_mech +gss_inquire_sec_context_by_oid +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_krb5_set_cred_rcache +gss_krb5int_make_seal_token_v3 +gss_krb5int_unseal_token_v3 +gsskrb5_extract_authtime_from_sec_context +gsskrb5_extract_authz_data_from_sec_context +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_set +gss_release_buffer +gss_release_cred +gss_release_iov_buffer +gss_release_name +gss_release_oid +gss_release_oid_set +gss_seal +gss_set_sec_context_option +gss_sign +gss_str_to_oid +gss_test_oid_set_member +gss_unseal +gss_unwrap +gss_unwrap_aead +gss_unwrap_iov +gss_verify +gss_verify_mic +gss_wrap +gss_wrap_aead +gss_wrap_iov +gss_wrap_iov_length +gss_wrap_size_limit +gssspi_set_cred_option +gssspi_mech_invoke +krb5_gss_dbg_client_expcreds +krb5_gss_register_acceptor_identity +krb5_gss_use_kdc_context diff --git a/krb5-1-7/src/lib/gssapi/mechglue/Makefile.in b/krb5-1-7/src/lib/gssapi/mechglue/Makefile.in new file mode 100644 index 000000000..927b3755c --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/Makefile.in @@ -0,0 +1,166 @@ +thisconfigdir=../../.. +myfulldir=lib/gssapi/mechglue +mydir=lib/gssapi/mechglue +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../krb5 -I$(srcdir)/../krb5 -I../spnego -I$(srcdir)/../spnego +DEFS=-D_GSS_STATIC_LINK=1 + +##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_buffer_set.c \ + $(srcdir)/g_canon_name.c \ + $(srcdir)/g_compare_name.c \ + $(srcdir)/g_complete_auth_token.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_context_oid.c \ + $(srcdir)/g_inq_cred.c \ + $(srcdir)/g_inq_cred_oid.c \ + $(srcdir)/g_inq_names.c \ + $(srcdir)/g_mech_invoke.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_set_context_option.c \ + $(srcdir)/g_set_cred_option.c \ + $(srcdir)/g_sign.c \ + $(srcdir)/g_store_cred.c \ + $(srcdir)/g_unseal.c \ + $(srcdir)/g_unwrap_aead.c \ + $(srcdir)/g_unwrap_iov.c \ + $(srcdir)/g_verify.c \ + $(srcdir)/g_wrap_aead.c \ + $(srcdir)/g_wrap_iov.c + +OBJS = \ + $(OUTPRE)g_accept_sec_context.$(OBJEXT) \ + $(OUTPRE)g_acquire_cred.$(OBJEXT) \ + $(OUTPRE)g_buffer_set.$(OBJEXT) \ + $(OUTPRE)g_canon_name.$(OBJEXT) \ + $(OUTPRE)g_compare_name.$(OBJEXT) \ + $(OUTPRE)g_complete_auth_token.$(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_context_oid.$(OBJEXT) \ + $(OUTPRE)g_inq_cred.$(OBJEXT) \ + $(OUTPRE)g_inq_cred_oid.$(OBJEXT) \ + $(OUTPRE)g_inq_names.$(OBJEXT) \ + $(OUTPRE)g_mech_invoke.$(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_set_context_option.$(OBJEXT) \ + $(OUTPRE)g_set_cred_option.$(OBJEXT) \ + $(OUTPRE)g_sign.$(OBJEXT) \ + $(OUTPRE)g_store_cred.$(OBJEXT) \ + $(OUTPRE)g_unseal.$(OBJEXT) \ + $(OUTPRE)g_unwrap_aead.$(OBJEXT) \ + $(OUTPRE)g_unwrap_iov.$(OBJEXT) \ + $(OUTPRE)g_verify.$(OBJEXT) \ + $(OUTPRE)g_wrap_aead.$(OBJEXT) \ + $(OUTPRE)g_wrap_iov.$(OBJEXT) + +STLIBOBJS = \ + g_accept_sec_context.o \ + g_acquire_cred.o \ + g_buffer_set.o \ + g_canon_name.o \ + g_compare_name.o \ + g_complete_auth_token.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_context_oid.o \ + g_inq_cred.o \ + g_inq_cred_oid.o \ + g_inq_names.o \ + g_mech_invoke.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_set_context_option.o \ + g_set_cred_option.o \ + g_sign.o \ + g_store_cred.o \ + g_unseal.o \ + g_unwrap_aead.o \ + g_unwrap_iov.o \ + g_verify.o \ + g_wrap_aead.o \ + g_wrap_iov.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@ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/deps b/krb5-1-7/src/lib/gssapi/mechglue/deps new file mode 100644 index 000000000..c54fae9f2 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/deps @@ -0,0 +1,343 @@ +# +# Generated makefile dependencies follow. +# +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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_acquire_cred.c mechglue.h \ + mglueP.h +g_buffer_set.so g_buffer_set.po $(OUTPRE)g_buffer_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_buffer_set.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_compare_name.c mechglue.h \ + mglueP.h +g_complete_auth_token.so g_complete_auth_token.po $(OUTPRE)g_complete_auth_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_complete_auth_token.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(srcdir)/../krb5/gssapiP_krb5.h $(srcdir)/../spnego/gssapiP_spnego.h \ + ../generic/gssapi_err_generic.h ../krb5/gssapi_err_krb5.h \ + ../krb5/gssapi_krb5.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_inq_context.c mechglue.h \ + mglueP.h +g_inq_context_oid.so g_inq_context_oid.po $(OUTPRE)g_inq_context_oid.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_inq_context_oid.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_inq_cred.c mechglue.h \ + mglueP.h +g_inq_cred_oid.so g_inq_cred_oid.po $(OUTPRE)g_inq_cred_oid.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_inq_cred_oid.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_inq_names.c mechglue.h \ + mglueP.h +g_mech_invoke.so g_mech_invoke.po $(OUTPRE)g_mech_invoke.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_mech_invoke.c mechglue.h \ + mglueP.h +g_mechname.so g_mechname.po $(OUTPRE)g_mechname.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_seal.c mechglue.h \ + mglueP.h +g_set_context_option.so g_set_context_option.po $(OUTPRE)g_set_context_option.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_set_context_option.c \ + mechglue.h mglueP.h +g_set_cred_option.so g_set_cred_option.po $(OUTPRE)g_set_cred_option.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_set_cred_option.c \ + mechglue.h mglueP.h +g_sign.so g_sign.po $(OUTPRE)g_sign.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.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 \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_unseal.c mechglue.h \ + mglueP.h +g_unwrap_aead.so g_unwrap_aead.po $(OUTPRE)g_unwrap_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_unwrap_aead.c mechglue.h \ + mglueP.h +g_unwrap_iov.so g_unwrap_iov.po $(OUTPRE)g_unwrap_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_unwrap_iov.c mechglue.h \ + mglueP.h +g_verify.so g_verify.po $(OUTPRE)g_verify.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_verify.c mechglue.h \ + mglueP.h +g_wrap_aead.so g_wrap_aead.po $(OUTPRE)g_wrap_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_wrap_aead.c mechglue.h \ + mglueP.h +g_wrap_iov.so g_wrap_iov.po $(OUTPRE)g_wrap_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + ../generic/gssapi_err_generic.h g_wrap_iov.c mechglue.h \ + mglueP.h diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_accept_sec_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_accept_sec_context.c new file mode 100644 index 000000000..fa703d34d --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_accept_sec_context.c @@ -0,0 +1,361 @@ +/* #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 +#endif +#include +#include + +#ifndef LEAN_CLIENT +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 (input_token_buffer == GSS_C_NO_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(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) { + map_error(minor_status, mech); + 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; + map_error(minor_status, mech); + if (output_token->length) + (void) gss_release_buffer(&temp_minor_status, + output_token); + if (internal_name != GSS_C_NO_NAME) + mech->gss_release_name( + &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; + } + + 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(minor_status, + tmp_d_cred, + &internal_name, + &d_u_cred->auxinfo.time_rec, + &d_u_cred->auxinfo.cred_usage, + NULL); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } + + 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; + map_error(minor_status, mech); + 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); +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_acquire_cred.c b/krb5-1-7/src/lib/gssapi/mechglue/g_acquire_cred.c new file mode 100644 index 000000000..fada9e887 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -0,0 +1,536 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include + +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); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + 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; + unsigned 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); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + 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; + else + time_req = 0; + + status = mech->gss_acquire_cred(minor_status, + internal_name, time_req, + GSS_C_NULL_OID_SET, cred_usage, + &cred, NULL, &time_rec); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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( + &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(&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(&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-7/src/lib/gssapi/mechglue/g_buffer_set.c b/krb5-1-7/src/lib/gssapi/mechglue/g_buffer_set.c new file mode 100644 index 000000000..1b2621c6b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_buffer_set.c @@ -0,0 +1,57 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_create_empty_buffer_set(minor_status, buffer_set); +} + +OM_uint32 KRB5_CALLCONV gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_add_buffer_set_member(minor_status, + member_buffer, + buffer_set); +} + +OM_uint32 KRB5_CALLCONV gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_release_buffer_set(minor_status, buffer_set); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_canon_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_canon_name.c new file mode 100644 index 000000000..3d371c0e0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_canon_name.c @@ -0,0 +1,188 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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) { + major_status = generic_gss_copy_oid(minor_status, + in_union->name_type, + &out_union->name_type); + if (major_status) { + map_errcode(minor_status); + 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))) { + map_errcode(minor_status); + 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-7/src/lib/gssapi/mechglue/g_compare_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_compare_name.c new file mode 100644 index 000000000..153e9b615 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_compare_name.c @@ -0,0 +1,210 @@ +/* #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 +#endif +#include + +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 = NULL; + 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); + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_compare_name) + return (GSS_S_UNAVAILABLE); + major_status = mech->gss_compare_name(minor_status, + union_name1->mech_name, + union_name2->mech_name, + name_equal); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; + } + + /* + * 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 */ + + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_compare_name) + return (GSS_S_UNAVAILABLE); + major_status = mech->gss_compare_name(minor_status, + union_name1->mech_name, + internal_name, name_equal); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + gssint_release_internal_name(&temp_minor, union_name1->mech_type, + &internal_name); + return (major_status); + +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_complete_auth_token.c b/krb5-1-7/src/lib/gssapi/mechglue/g_complete_auth_token.c new file mode 100644 index 000000000..918155130 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_complete_auth_token.c @@ -0,0 +1,70 @@ +/* #ident "@(#)gss_seal.c 1.10 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. + */ + +/* + * glue routine for gss_complete_auth_token + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_complete_auth_token (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (context_handle == GSS_C_NO_CONTEXT) + return 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 != NULL) { + if (mech->gss_complete_auth_token != NULL) { + status = mech->gss_complete_auth_token(minor_status, + ctx->internal_ctx_id, + input_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_COMPLETE; + } else + status = GSS_S_BAD_MECH; + + return status; +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_context_time.c b/krb5-1-7/src/lib/gssapi/mechglue/g_context_time.c new file mode 100644 index 000000000..4293b078e --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_context_time.c @@ -0,0 +1,79 @@ +/* #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( + minor_status, + ctx->internal_ctx_id, + time_rec); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_delete_sec_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_delete_sec_context.c new file mode 100644 index 000000000..2fcd3c2d1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_delete_sec_context.c @@ -0,0 +1,104 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#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; + + 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); + + status = gssint_delete_internal_sec_context(minor_status, + ctx->mech_type, + &ctx->internal_ctx_id, + output_token); + if (status) + return status; + + /* now free up the space for the union context structure */ + free(ctx->mech_type->elements); + free(ctx->mech_type); + free(*context_handle); + *context_handle = GSS_C_NO_CONTEXT; + + return (GSS_S_COMPLETE); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_dsp_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_dsp_name.c new file mode 100644 index 000000000..7efd583f8 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_dsp_name.c @@ -0,0 +1,138 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +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) { + map_errcode(minor_status); + 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-7/src/lib/gssapi/mechglue/g_dsp_status.c b/krb5-1-7/src/lib/gssapi/mechglue/g_dsp_status.c new file mode 100644 index 000000000..49b79e15d --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_dsp_status.c @@ -0,0 +1,368 @@ +/* #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 +#include +#include + +/* 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; + gss_OID_desc m_oid = { 0, 0 }; + + 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. + */ + + /* In this version, we only handle status codes that have been + mapped to a flat numbering space. Look up the value we got + passed. If it's not found, complain. */ + if (status_value == 0) { + status_string->value = strdup("Unknown error"); + if (status_string->value == NULL) { + *minor_status = ENOMEM; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + status_string->length = strlen(status_string->value); + *message_context = 0; + *minor_status = 0; + return GSS_S_COMPLETE; + } + { + int err; + OM_uint32 m_status = 0, status; + + err = gssint_mecherrmap_get(status_value, &m_oid, &m_status); + if (err) { + *minor_status = err; + map_errcode(minor_status); + return GSS_S_BAD_STATUS; + } + if (m_oid.length == 0) { + /* Magic flag for com_err values. */ + status = g_display_com_err_status(minor_status, m_status, status_string); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; + } + mech_type = &m_oid; + status_value = m_status; + } + + mech = gssint_get_mechanism (mech_type); + + if (mech && mech->gss_display_status) { + OM_uint32 r; + + r = mech->gss_display_status(minor_status, + status_value, status_type, mech_type, + message_context, status_string); + /* How's this for weird? If we get an error returning the + mechanism-specific error code, we save away the + mechanism-specific error code describing the error. */ + if (r != GSS_S_COMPLETE) + map_error(minor_status, mech); + return r; + } + + 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 = strdup(errStr); + if (outStr->value == NULL) { + outStr->length = 0; + return (GSS_S_FAILURE); + } + + return (GSS_S_COMPLETE); +} /* displayMajor */ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_dup_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_dup_name.c new file mode 100644 index 000000000..9312de761 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_dup_name.c @@ -0,0 +1,144 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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) { + map_errcode(minor_status); + 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) { + map_errcode(minor_status); + 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-7/src/lib/gssapi/mechglue/g_exp_sec_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_exp_sec_context.c new file mode 100644 index 000000000..f2ee5a5b7 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_exp_sec_context.c @@ -0,0 +1,139 @@ +/* #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 + */ +#ifndef LEAN_CLIENT + +#include "mglueP.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +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(minor_status, + &ctx->internal_ctx_id, &token); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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); +} +#endif /*LEAN_CLIENT */ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_export_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_export_name.c new file mode 100644 index 000000000..d9545b798 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_export_name.c @@ -0,0 +1,59 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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-7/src/lib/gssapi/mechglue/g_glue.c b/krb5-1-7/src/lib/gssapi/mechglue/g_glue.c new file mode 100644 index 000000000..5a8ea54b1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_glue.c @@ -0,0 +1,680 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +#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; + unsigned 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, *p; + unsigned int buf_len = 0; + int i, first; + + /* Oops */ + if (buf == 0 || max_len < 1) + return (-1); + + s = *buf; + + /* 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(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 + * + * + * Numerically, this looks like : + * + * 0x60 + * - could be multiple bytes + * 0x06 + * - assume only one byte, hence OID length < 127 + * + * + * 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); +} + +/* + * The following mechanisms do not always identify themselves + * per the GSS-API specification, when interoperating with MS + * peers. We include the OIDs here so we do not have to ilnk + * with the mechanism. + */ +static gss_OID_desc gss_ntlm_mechanism_oid_desc = + {10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; +static gss_OID_desc gss_spnego_mechanism_oid_desc = + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; +static gss_OID_desc gss_krb5_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +#define NTLMSSP_SIGNATURE "NTLMSSP" + +OM_uint32 gssint_get_mech_type(OID, token) + gss_OID OID; + gss_buffer_t token; +{ + /* Check for interoperability exceptions */ + if (token->length >= sizeof(NTLMSSP_SIGNATURE) && + memcmp(token->value, NTLMSSP_SIGNATURE, + sizeof(NTLMSSP_SIGNATURE)) == 0) { + *OID = gss_ntlm_mechanism_oid_desc; + } else if (token->length != 0 && + ((char *)token->value)[0] == 0x6E) { + /* Could be a raw AP-REQ (check for APPLICATION tag) */ + *OID = gss_krb5_mechanism_oid_desc; + } else if (token->length == 0) { + *OID = gss_spnego_mechanism_oid_desc; + } else { + return gssint_get_mech_type_oid(OID, token); + } + + 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 ( + minor_status, + union_name->external_name, + union_name->name_type, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } 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) { + status = mech->gss_export_name(minor_status, + internal_name, + name_buf); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; + } + + /* + * 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(minor_status, + internal_name, + &dispName, + &nameOid)) + != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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; + store_16_be(mechOidLen, buf); + buf += 2; + + /* + * 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 */ + store_32_be(dispName.length, buf); + buf += 4; + + /* 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 ( + minor_status, + internal_name, + external_name, + name_type); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } 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 ( + minor_status, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return (status); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 gssint_delete_internal_sec_context (minor_status, + mech_type, + internal_ctx, + output_token) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_ctx_id_t *internal_ctx; +gss_buffer_t output_token; +{ + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_delete_sec_context) + status = mech->gss_delete_sec_context (minor_status, + internal_ctx, + output_token); + 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) { + major_status = GSS_S_FAILURE; + *minor_status = ENOMEM; + map_errcode(minor_status); + 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) { + map_errcode(minor_status); + goto allocation_failure; + } + + union_name->external_name = + (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); + if (!union_name->external_name) { + major_status = GSS_S_FAILURE; + goto allocation_failure; + } + + major_status = mech->gss_display_name(minor_status, + internal_name, + union_name->external_name, + &union_name->name_type); + if (major_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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; + + /* SPNEGO mechanism will again call into GSSAPI */ + if (g_OID_equal(&gss_spnego_mechanism_oid_desc, mech_type)) + return (gss_cred_id_t)union_cred; + + 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]; + + /* for SPNEGO, check the next-lower set of creds */ + if (g_OID_equal(&gss_spnego_mechanism_oid_desc, &union_cred->mechs_array[i])) { + gss_union_cred_t candidate_cred; + gss_cred_id_t sub_cred; + + candidate_cred = (gss_union_cred_t)union_cred->cred_array[i]; + sub_cred = gssint_get_mechanism_cred(candidate_cred, mech_type); + + if(sub_cred != GSS_C_NO_CREDENTIAL) + return sub_cred; + } + } + 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-7/src/lib/gssapi/mechglue/g_imp_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_imp_name.c new file mode 100644 index 000000000..c4767bf3e --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_imp_name.c @@ -0,0 +1,366 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +/* 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) { + map_errcode(minor_status); + 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) { + major = mech->gss_import_name(minor, + &expName, (gss_OID)GSS_C_NT_EXPORT_NAME, + &unionName->mech_name); + if (major != GSS_S_COMPLETE) + map_error(minor, mech); + else { + major = generic_gss_copy_oid(minor, &mechOid, + &unionName->mech_type); + if (major != GSS_S_COMPLETE) + map_errcode(minor); + } + 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 = load_32_be(buf); + buf += 4; + + /* + * 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(minor, &expName, + GSS_C_NULL_OID, &unionName->mech_name); + if (major != GSS_S_COMPLETE) { + map_error(minor, mech); + return (major); + } + + major = generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type); + if (major != GSS_S_COMPLETE) { + map_errcode(minor); + } + return major; +} /* importExportName */ + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_imp_sec_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_imp_sec_context.c new file mode 100644 index 000000000..7aa1165b0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_imp_sec_context.c @@ -0,0 +1,167 @@ +/* #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 + */ + +#ifndef LEAN_CLIENT + +#include "mglueP.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +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(minor_status, + &token, &ctx->internal_ctx_id); + + if (status == GSS_S_COMPLETE) { + ctx->loopback = ctx; + *context_handle = ctx; + return (GSS_S_COMPLETE); + } + map_error(minor_status, mech); + +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; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_init_sec_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_init_sec_context.c new file mode 100644 index 000000000..10c8bf971 --- /dev/null +++ b/krb5-1-7/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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +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( + 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 + */ + map_error(minor_status, mech); + 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-7/src/lib/gssapi/mechglue/g_initialize.c b/krb5-1-7/src/lib/gssapi/mechglue/g_initialize.c new file mode 100644 index 000000000..1149384a2 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_initialize.c @@ -0,0 +1,1198 @@ +/* #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" +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include +#include +#include +#include + +#define M_DEFAULT "default" + +#include "k5-thread.h" +#include "k5-plugin.h" +#include "osconf.h" +#ifdef _GSS_STATIC_LINK +#include "gssapiP_krb5.h" +#include "gssapiP_spnego.h" +#endif + +#define MECH_SYM "gss_mech_initialize" + +#ifndef MECH_CONF +#define MECH_CONF "/etc/gss/mech" +#endif + +/* Local functions */ +static gss_mech_info searchMechList(const gss_OID); +static void loadConfigFile(const char *); +static void updateMechList(void); +static void freeMechList(void); + +static OM_uint32 build_mechSet(void); +static void free_mechSet(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 time_t g_confFileModTime = (time_t)0; + +static time_t g_mechSetTime = (time_t)0; +static gss_OID_set_desc g_mechSet = { 0, NULL }; +static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER; + +MAKE_INIT_FUNCTION(gssint_mechglue_init); +MAKE_FINI_FUNCTION(gssint_mechglue_fini); + +int +gssint_mechglue_init(void) +{ + int err; + +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_init\n"); +#endif + + add_error_table(&et_ggss_error_table); + + err = k5_mutex_finish_init(&g_mechSetLock); + err = k5_mutex_finish_init(&g_mechListLock); + +#ifdef _GSS_STATIC_LINK + err = gss_krb5int_lib_init(); + err = gss_spnegoint_lib_init(); +#endif + + return err; +} + +void +gssint_mechglue_fini(void) +{ + if (!INITIALIZER_RAN(gssint_mechglue_init) || PROGRAM_EXITING()) { +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_fini: skipping\n"); +#endif + return; + } + +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_fini\n"); +#endif +#ifdef _GSS_STATIC_LINK + gss_spnegoint_lib_fini(); + gss_krb5int_lib_fini(); +#endif + k5_mutex_destroy(&g_mechSetLock); + k5_mutex_destroy(&g_mechListLock); + free_mechSet(); + freeMechList(); + remove_error_table(&et_ggss_error_table); + gssint_mecherrmap_destroy(); +} + +int +gssint_mechglue_initialize_library(void) +{ + return CALL_INIT_FUNCTION(gssint_mechglue_init); +} + +/* + * 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 (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minor_status = gssint_mechglue_initialize_library(); + if (*minor_status != 0) + return (GSS_S_FAILURE); + + *minor_status = k5_mutex_lock(&g_mechListLock); + if (*minor_status) + return GSS_S_FAILURE; + 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( + minor_status, oid); + if (major == GSS_S_COMPLETE) { + k5_mutex_unlock(&g_mechListLock); + return (GSS_S_COMPLETE); + } + map_error(minor_status, aMech->mech); + } + 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; +{ + char *fileName; + struct stat fileInfo; + unsigned 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); + + *minorStatus = gssint_mechglue_initialize_library(); + if (*minorStatus != 0) + return (GSS_S_FAILURE); + + fileName = MECH_CONF; + + /* + * If we have already computed the mechanisms supported and if it + * is still valid; make a copy and return to caller, + * otherwise build it first. + */ + if ((stat(fileName, &fileInfo) == 0 && + fileInfo.st_mtime > g_mechSetTime)) { + } /* if g_mechSet is out of date or not initialized */ + 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. + */ + *minorStatus = k5_mutex_lock(&g_mechSetLock); + if (*minorStatus) + return GSS_S_FAILURE; + + /* 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 */ + + +/* Call with g_mechSetLock held, or during final cleanup. */ +static void +free_mechSet(void) +{ + unsigned int i; + + 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; + } +} + +static OM_uint32 +build_mechSet(void) +{ + gss_mech_info mList; + size_t i; + size_t 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. + */ + if (k5_mutex_lock(&g_mechListLock) != 0) + return GSS_S_FAILURE; + +#if 0 + /* + * this checks for the case when we need to re-construct the + * g_mechSet structure, but the mechanism list is upto date + * (because it has been read by someone calling + * gssint_get_mechanism) + */ + if (fileInfo.st_mtime > g_confFileModTime) + { + g_confFileModTime = fileInfo.st_mtime; + loadConfigFile(fileName); + } +#endif + + updateMechList(); + + /* + * we need to lock the mech set so that no one else will + * try to read it as we are re-creating it + */ + if (k5_mutex_lock(&g_mechSetLock) != 0) + return GSS_S_FAILURE; + + /* if the oid list already exists we must free it first */ + free_mechSet(); + + /* 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; + } + } + +#if 0 + g_mechSetTime = fileInfo.st_mtime; +#endif + (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; + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + /* make sure we have fresh data */ + if (k5_mutex_lock(&g_mechListLock) != 0) + return NULL; + 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 (gssint_mechglue_initialize_library() != 0) + return (GSS_S_FAILURE); + + if ((mechStr == NULL) || (strlen(mechStr) == 0) || + (strcasecmp(mechStr, M_DEFAULT) == 0)) + return (GSS_S_COMPLETE); + + /* ensure we have fresh data */ + if (k5_mutex_lock(&g_mechListLock) != 0) + return GSS_S_FAILURE; + 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); + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + /* ensure we have fresh data */ + if (k5_mutex_lock(&g_mechListLock) != 0) + return NULL; + 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 (mechArray == NULL || arrayLen < 1) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (gssint_mechglue_initialize_library() != 0) + return (GSS_S_FAILURE); + + /* ensure we have fresh data */ + if (k5_mutex_lock(&g_mechListLock) != 0) + return GSS_S_FAILURE; + 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) +{ + char *fileName; + struct stat fileInfo; + + fileName = MECH_CONF; + + /* check if mechList needs updating */ + if (stat(fileName, &fileInfo) == 0 && + (fileInfo.st_mtime > g_confFileModTime)) { + loadConfigFile(fileName); + g_confFileModTime = fileInfo.st_mtime; + } +#if 0 + init_hardcoded(); +#endif +} /* updateMechList */ + +#ifdef _GSS_STATIC_LINK +static void +releaseMechInfo(gss_mech_info *pCf) +{ + gss_mech_info cf; + OM_uint32 minor_status; + + if (*pCf == NULL) { + return; + } + + cf = *pCf; + + if (cf->kmodName != NULL) + free(cf->kmodName); + if (cf->uLibName != NULL) + free(cf->uLibName); + if (cf->mechNameStr != NULL) + free(cf->mechNameStr); + if (cf->optionStr != NULL) + free(cf->optionStr); + if (cf->mech_type != GSS_C_NO_OID && + cf->mech_type != &cf->mech->mech_type) + generic_gss_release_oid(&minor_status, &cf->mech_type); + if (cf->mech != NULL) { + memset(cf->mech, 0, sizeof(*cf->mech)); + free(cf->mech); + } + if (cf->dl_handle != NULL) + krb5int_close_plugin(cf->dl_handle); + + memset(cf, 0, sizeof(*cf)); + free(cf); + + *pCf = NULL; +} + +/* + * Register a mechanism. Called with g_mechListLock held. + */ +int +gssint_register_mechinfo(gss_mech_info template) +{ + gss_mech_info cf, new_cf; + + new_cf = calloc(1, sizeof(*new_cf)); + if (new_cf == NULL) { + return ENOMEM; + } + + new_cf->dl_handle = template->dl_handle; + /* copy mech so we can rewrite canonical mechanism OID */ + new_cf->mech = (gss_mechanism)calloc(1, sizeof(struct gss_config)); + if (new_cf->mech == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + memcpy(new_cf->mech, template->mech, sizeof(struct gss_config)); + if (template->mech_type != NULL) + new_cf->mech->mech_type = *(template->mech_type); + new_cf->mech_type = &new_cf->mech->mech_type; + new_cf->priority = template->priority; + new_cf->freeMech = 1; + new_cf->next = NULL; + + if (template->kmodName != NULL) { + new_cf->kmodName = strdup(template->kmodName); + if (new_cf->kmodName == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->uLibName != NULL) { + new_cf->uLibName = strdup(template->uLibName); + if (new_cf->uLibName == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->mechNameStr != NULL) { + new_cf->mechNameStr = strdup(template->mechNameStr); + if (new_cf->mechNameStr == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->optionStr != NULL) { + new_cf->optionStr = strdup(template->optionStr); + if (new_cf->optionStr == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (g_mechList == NULL) { + g_mechList = new_cf; + g_mechListTail = new_cf; + return 0; + } else if (new_cf->priority < g_mechList->priority) { + new_cf->next = g_mechList; + g_mechList = new_cf; + return 0; + } + + for (cf = g_mechList; cf != NULL; cf = cf->next) { + if (cf->next == NULL || + new_cf->priority < cf->next->priority) { + new_cf->next = cf->next; + cf->next = new_cf; + if (g_mechListTail == cf) { + g_mechListTail = new_cf; + } + break; + } + } + + return 0; +} +#endif /* _GSS_STATIC_LINK */ + +#define GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol) \ + do { \ + struct errinfo errinfo; \ + \ + memset(&errinfo, 0, sizeof(errinfo)); \ + if (krb5int_get_plugin_func(_dl, \ + #_symbol, \ + (void (**)())&(_mech)->_symbol, \ + &errinfo) || errinfo.code) \ + (_mech)->_symbol = NULL; \ + } while (0) + +static gss_mechanism +build_dynamicMech(void *dl, const gss_OID mech_type) +{ + gss_mechanism mech; + + mech = (gss_mechanism)calloc(1, sizeof(*mech)); + if (mech == NULL) { + return NULL; + } + + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_acquire_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_release_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_init_sec_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_accept_sec_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_process_context_token); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_delete_sec_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_context_time); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_get_mic); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_verify_mic); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_unwrap); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_display_status); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_indicate_mechs); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_compare_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_display_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_import_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_release_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_add_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_sec_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_import_sec_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_cred_by_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_names_for_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_internal_release_oid); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_size_limit); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_store_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_sec_context_by_oid); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_cred_by_oid); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_set_sec_context_option); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_set_cred_option); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_mech_invoke); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_aead); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_unwrap_aead); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_iov); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_unwrap_iov); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_iov_length); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_complete_auth_token); + + assert(mech_type != GSS_C_NO_OID); + + mech->mech_type = *(mech_type); + + return mech; +} + +static void +freeMechList(void) +{ + gss_mech_info cf, next_cf; + OM_uint32 minor; + + for (cf = g_mechList; cf != NULL; cf = next_cf) { + next_cf = cf->next; + if (cf->kmodName != NULL) + free(cf->kmodName); + if (cf->uLibName != NULL) + free(cf->uLibName); + if (cf->mechNameStr != NULL) + free(cf->mechNameStr); + if (cf->optionStr != NULL) + free(cf->optionStr); + if (cf->mech_type != &cf->mech->mech_type) + generic_gss_release_oid(&minor, &cf->mech_type); + if (cf->mech != NULL && cf->freeMech) + free(cf->mech); + if (cf->mech_ext != NULL && cf->freeMech) + free(cf->mech_ext); + if (cf->dl_handle != NULL) + (void) krb5int_close_plugin(cf->dl_handle); + free(cf); + } +} + +/* + * Register a mechanism. Called with g_mechListLock held. + */ + +/* + * 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(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + gss_mechanism (*sym)(const gss_OID); + struct plugin_file_handle *dl; + struct errinfo errinfo; + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + if (k5_mutex_lock(&g_mechListLock) != 0) + return NULL; + /* 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); + } + + memset(&errinfo, 0, sizeof(errinfo)); + + if (krb5int_open_plugin(aMech->uLibName, &dl, &errinfo) != 0 || + errinfo.code != 0) { +#if 0 + (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n", + aMech->uLibName, dlerror()); +#endif + (void) k5_mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + if (krb5int_get_plugin_func(dl, MECH_SYM, (void (**)())&sym, + &errinfo) == 0) { + /* Call the symbol to get the mechanism table */ + aMech->mech = (*sym)(aMech->mech_type); + } else { + /* Try dynamic dispatch table */ + aMech->mech = build_dynamicMech(dl, aMech->mech_type); + aMech->freeMech = 1; + } + if (aMech->mech == NULL) { + (void) krb5int_close_plugin(dl); +#if 0 + (void) syslog(LOG_INFO, "unable to initialize mechanism" + " library [%s]\n", aMech->uLibName); +#endif + (void) k5_mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + aMech->dl_handle = dl; + + (void) k5_mutex_unlock(&g_mechListLock); + return (aMech->mech); +} /* gssint_get_mechanism */ + +gss_mechanism_ext +gssint_get_mechanism_ext(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + gss_mechanism_ext mech_ext; + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + /* check if the mechanism is already loaded */ + if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL) + return (aMech->mech_ext); + + if (gssint_get_mechanism(oid) == NULL) + return (NULL); + + if (aMech->dl_handle == NULL) + return (NULL); + + /* Load the gss_config_ext struct for this mech */ + + mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext)); + + if (mech_ext == NULL) + return (NULL); + +#if 0 + /* + * dlsym() the mech's 'method' functions for the extended APIs + * + * NOTE: Until the void *context argument is removed from the + * SPI method functions' signatures it will be necessary to have + * different function pointer typedefs and function names for + * the SPI methods than for the API. When this argument is + * removed it will be possible to rename gss_*_sfct to gss_*_fct + * and and gssspi_* to gss_*. + */ + mech_ext->gss_acquire_cred_with_password = + (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle, + "gssspi_acquire_cred_with_password"); +#endif + + /* Set aMech->mech_ext */ + (void) k5_mutex_lock(&g_mechListLock); + + if (aMech->mech_ext == NULL) + aMech->mech_ext = mech_ext; + else + free(mech_ext); /* we raced and lost; don't leak */ + + (void) k5_mutex_unlock(&g_mechListLock); + + return (aMech->mech_ext); + +} /* gssint_get_mechanism_ext */ + + +/* + * 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 */ + + +/* + * loads the configuration file + * this is called while having a mutex lock on the mechanism list + * entries for libraries that have been loaded can't be modified + * mechNameStr and mech_type fields are not updated during updates + */ +static void loadConfigFile(fileName) +const char *fileName; +{ + char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp; + char *modOptions; + char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ]; + char *tmpStr; + FILE *confFile; + gss_OID mechOid; + gss_mech_info aMech, tmp; + OM_uint32 minor; + gss_buffer_desc oidBuf; + + if ((confFile = fopen(fileName, "r")) == NULL) { + return; + } + + (void) memset(buffer, 0, sizeof (buffer)); + while (fgets(buffer, BUFSIZ, confFile) != NULL) { + + /* ignore lines beginning with # */ + if (*buffer == '#') + continue; + + /* + * find the first white-space character after + * the mechanism name + */ + oidStr = buffer; + for (oid = buffer; *oid && !isspace(*oid); oid++); + + /* Now find the first non-white-space character */ + if (*oid) { + *oid = '\0'; + oid++; + while (*oid && isspace(*oid)) + oid++; + } + + /* + * If that's all, then this is a corrupt entry. Skip it. + */ + if (! *oid) + continue; + + /* Find the end of the oid and make sure it is NULL-ended */ + for (endp = oid; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + + /* + * check if an entry for this oid already exists + * if it does, and the library is already loaded then + * we can't modify it, so skip it + */ + oidBuf.value = (void *)oid; + oidBuf.length = strlen(oid); + if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid) + != GSS_S_COMPLETE) { +#if 0 + (void) syslog(LOG_INFO, "invalid mechanism oid" + " [%s] in configuration file", oid); +#endif + continue; + } + + aMech = searchMechList(mechOid); + if (aMech && aMech->mech) { + generic_gss_release_oid(&minor, &mechOid); + continue; + } + + /* Find the start of the shared lib name */ + for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib); + sharedLib++) + ; + + /* + * If that's all, then this is a corrupt entry. Skip it. + */ + if (! *sharedLib) { + generic_gss_release_oid(&minor, &mechOid); + continue; + } + + /* + * Find the end of the shared lib name and make sure it is + * NULL-terminated. + */ + for (endp = sharedLib; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + + /* Find the start of the optional kernel module lib name */ + for (kernMod = endp+1; *kernMod && isspace(*kernMod); + kernMod++) + ; + + /* + * If this item starts with a bracket "[", then + * it is not a kernel module, but is a list of + * options for the user module to parse later. + */ + if (*kernMod && *kernMod != '[') { + /* + * Find the end of the shared lib name and make sure + * it is NULL-terminated. + */ + for (endp = kernMod; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + } else + kernMod = NULL; + + /* Find the start of the optional module options list */ + for (modOptions = endp+1; *modOptions && isspace(*modOptions); + modOptions++); + + if (*modOptions == '[') { + /* move past the opening bracket */ + for (modOptions = modOptions+1; + *modOptions && isspace(*modOptions); + modOptions++); + + /* Find the closing bracket */ + for (endp = modOptions; + *endp && *endp != ']'; endp++); + + *endp = '\0'; + } else { + modOptions = NULL; + } + + snprintf(sharedPath, sizeof(sharedPath), "%s%s", MECH_LIB_PREFIX, sharedLib); + + /* + * are we creating a new mechanism entry or + * just modifying existing (non loaded) mechanism entry + */ + if (aMech) { + /* + * delete any old values and set new + * mechNameStr and mech_type are not modified + */ + if (aMech->kmodName) { + free(aMech->kmodName); + aMech->kmodName = NULL; + } + + if (aMech->optionStr) { + free(aMech->optionStr); + aMech->optionStr = NULL; + } + + if ((tmpStr = strdup(sharedPath)) != NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + aMech->uLibName = tmpStr; + } + + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) /* optional module options */ + aMech->optionStr = strdup(modOptions); + + /* the oid is already set */ + generic_gss_release_oid(&minor, &mechOid); + continue; + } + + /* adding a new entry */ + aMech = calloc(1, sizeof (struct gss_mech_config)); + if (aMech == NULL) { + generic_gss_release_oid(&minor, &mechOid); + continue; + } + aMech->mech_type = mechOid; + aMech->uLibName = strdup(sharedPath); + aMech->mechNameStr = strdup(oidStr); + aMech->freeMech = 0; + + /* check if any memory allocations failed - bad news */ + if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + if (aMech->mechNameStr) + free(aMech->mechNameStr); + generic_gss_release_oid(&minor, &mechOid); + free(aMech); + continue; + } + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) + aMech->optionStr = strdup(modOptions); + /* + * add the new entry to the end of the list - make sure + * that only complete entries are added because other + * threads might currently be searching the list. + */ + tmp = g_mechListTail; + g_mechListTail = aMech; + + if (tmp != NULL) + tmp->next = aMech; + + if (g_mechList == NULL) + g_mechList = aMech; + } /* while */ + (void) fclose(confFile); +} /* loadConfigFile */ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_inq_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_context.c new file mode 100644 index 000000000..013b1768b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_context.c @@ -0,0 +1,160 @@ +/* #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 +#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 *opened) +{ + + /* 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( + 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 *opened) +{ + 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, opened); + 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( + minor_status, + ctx->internal_ctx_id, + (src_name ? &localSourceName : NULL), + (targ_name ? &localTargName : NULL), + lifetime_rec, + NULL, + ctx_flags, + locally_initiated, + opened); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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(&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-7/src/lib/gssapi/mechglue/g_inq_context_oid.c b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_context_oid.c new file mode 100644 index 000000000..50bfcb561 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_context_oid.c @@ -0,0 +1,72 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 routine for gss_inquire_sec_context_by_oid + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + 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; + + /* + * 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 != NULL) { + if (mech->gss_inquire_sec_context_by_oid != NULL) { + status = mech->gss_inquire_sec_context_by_oid(minor_status, + ctx->internal_ctx_id, + desired_object, + data_set); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_BAD_MECH; + + return status; + } + + return GSS_S_NO_CONTEXT; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred.c b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred.c new file mode 100644 index 000000000..a14424399 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred.c @@ -0,0 +1,278 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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(minor_status, + GSS_C_NO_CREDENTIAL, + name ? &internal_name : NULL, + lifetime, cred_usage, mechanisms); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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; + map_error(minor_status, mech); + 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 (union_cred->auxinfo.name.length == 0) { + *name = GSS_C_NO_NAME; + } else 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(minor_status, + mech_cred, mech_type, + name ? &internal_name : NULL, + initiator_lifetime, + acceptor_lifetime, cred_usage); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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; + map_error(minor_status, mech); + return (status); + } + } + + return (GSS_S_COMPLETE); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred_oid.c b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred_oid.c new file mode 100644 index 000000000..34056f6bd --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_cred_oid.c @@ -0,0 +1,133 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 routine for gss_inquire_cred_by_oid + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +static OM_uint32 append_to_buffer_set(OM_uint32 *minor_status, + gss_buffer_set_t *dst, + const gss_buffer_set_t src) +{ + size_t i; + OM_uint32 status; + + if (src == GSS_C_NO_BUFFER_SET) + return GSS_S_COMPLETE; + + if (*dst == GSS_C_NO_BUFFER_SET) { + status = gss_create_empty_buffer_set(minor_status, dst); + if (status != GSS_S_COMPLETE) + return status; + } + + status = GSS_S_COMPLETE; + + for (i = 0; i < src->count; i++) { + status = gss_add_buffer_set_member(minor_status, + &src->elements[i], + dst); + if (status != GSS_S_COMPLETE) + break; + } + + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gss_union_cred_t union_cred; + gss_mechanism mech; + int i; + gss_buffer_set_t union_set = GSS_C_NO_BUFFER_SET; + gss_buffer_set_t ret_set = GSS_C_NO_BUFFER_SET; + OM_uint32 status, minor; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + union_cred = (gss_union_cred_t) cred_handle; + + status = gss_create_empty_buffer_set(minor_status, &ret_set); + if (status != GSS_S_COMPLETE) { + return status; + } + + status = GSS_S_BAD_MECH; + + for (i = 0; i < union_cred->count; i++) { + mech = gssint_get_mechanism(&union_cred->mechs_array[i]); + if (mech == NULL) + continue; + + if (mech->gss_inquire_cred_by_oid == NULL) + continue; + + status = (mech->gss_inquire_cred_by_oid)(minor_status, + union_cred->cred_array[i], + desired_object, + &ret_set); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + continue; + } + + if (union_cred->count == 1) { + union_set = ret_set; + break; + } + + status = append_to_buffer_set(minor_status, &union_set, ret_set); + gss_release_buffer_set(&minor, &ret_set); + if (status != GSS_S_COMPLETE) + break; + } + + if (status != GSS_S_COMPLETE) + gss_release_buffer_set(&minor, &union_set); + + *data_set = union_set; + + return status; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_inq_names.c b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_names.c new file mode 100644 index 000000000..597ab9919 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_inq_names.c @@ -0,0 +1,191 @@ +/* #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( + minor_status, + mechanism, + name_types); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } 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-7/src/lib/gssapi/mechglue/g_mech_invoke.c b/krb5-1-7/src/lib/gssapi/mechglue/g_mech_invoke.c new file mode 100644 index 000000000..d753347d1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_mech_invoke.c @@ -0,0 +1,70 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 routine for gssspi_mech_invoke + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gssspi_mech_invoke (OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 status; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + mech = gssint_get_mechanism (desired_mech); + if (mech == NULL || mech->gssspi_mech_invoke == NULL) { + return GSS_S_BAD_MECH; + } + + status = mech->gssspi_mech_invoke(minor_status, + desired_mech, + desired_object, + value); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_mechname.c b/krb5-1-7/src/lib/gssapi/mechglue/g_mechname.c new file mode 100644 index 000000000..9ade23456 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_mechname.c @@ -0,0 +1,117 @@ +/* + * 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 +#endif + +#include +#include +#include + +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; + map_errcode(minor_status); + 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) { + map_errcode(minor_status); + goto allocation_failure; + } + major_status = generic_gss_copy_oid(minor_status, mech, + &p->mech); + if (major_status) { + map_errcode(minor_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-7/src/lib/gssapi/mechglue/g_oid_ops.c b/krb5-1-7/src/lib/gssapi/mechglue/g_oid_ops.c new file mode 100644 index 000000000..bd195239c --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_oid_ops.c @@ -0,0 +1,111 @@ +/* #pragma ident "@(#)g_oid_ops.c 1.11 98/01/22 SMI" */ +/* + * lib/gssapi/mechglue/g_oid_ops.c + * + * Copyright 1995, 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. + * + */ + +/* + * 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; +{ + OM_uint32 status; + status = generic_gss_create_empty_oid_set(minor_status, oid_set); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +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; +{ + OM_uint32 status; + status = generic_gss_add_oid_set_member(minor_status, member_oid, oid_set); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +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; +{ + OM_uint32 status = generic_gss_oid_to_str(minor_status, oid, oid_str); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +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; +{ + OM_uint32 status = generic_gss_str_to_oid(minor_status, oid_str, oid); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +OM_uint32 KRB5_CALLCONV +gssint_copy_oid_set( + OM_uint32 *minor_status, + const gss_OID_set_desc * const oidset, + gss_OID_set *new_oidset) +{ + return generic_gss_copy_oid_set(minor_status, oidset, new_oidset); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_process_context.c b/krb5-1-7/src/lib/gssapi/mechglue/g_process_context.c new file mode 100644 index 000000000..9ed350c02 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_process_context.c @@ -0,0 +1,82 @@ +/* #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( + minor_status, + ctx->internal_ctx_id, + token_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_rel_buffer.c b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_buffer.c new file mode 100644 index 000000000..6f8367a1d --- /dev/null +++ b/krb5-1-7/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 +#ifdef HAVE_STDLIB_H +#include +#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-7/src/lib/gssapi/mechglue/g_rel_cred.c b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_cred.c new file mode 100644 index 000000000..df208a0df --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_cred.c @@ -0,0 +1,102 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#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 (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL) + return (GSS_S_COMPLETE); + + if (GSSINT_CHK_LOOP(union_cred)) + return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ); + *cred_handle = NULL; + + 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 + ( + minor_status, + &union_cred->cred_array[j]); + + if (temp_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + 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-7/src/lib/gssapi/mechglue/g_rel_name.c b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_name.c new file mode 100644 index 000000000..84d1af839 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_name.c @@ -0,0 +1,86 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +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 == NULL) + 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_C_NO_OID) + gss_release_oid(minor_status, &union_name->name_type); + + if (union_name->external_name != GSS_C_NO_BUFFER) { + if (union_name->external_name->value != NULL) + 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-7/src/lib/gssapi/mechglue/g_rel_oid_set.c b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_oid_set.c new file mode 100644 index 000000000..84c6ce6c9 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_rel_oid_set.c @@ -0,0 +1,43 @@ +/* #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 +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 KRB5_CALLCONV +gss_release_oid_set (minor_status, + set) + +OM_uint32 * minor_status; +gss_OID_set * set; +{ + return generic_gss_release_oid_set(minor_status, set); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_seal.c b/krb5-1-7/src/lib/gssapi/mechglue/g_seal.c new file mode 100644 index 000000000..9faa5ddb0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_seal.c @@ -0,0 +1,272 @@ +/* #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_wrap + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_args( + 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) +{ + + /* 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_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; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_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_wrap) { + status = mech->gss_wrap( + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_wrap_aead || + (mech->gss_wrap_iov && mech->gss_wrap_iov_length)) { + status = gssint_wrap_aead(mech, + minor_status, + ctx, + conf_req_flag, + (gss_qop_t)qop_req, + GSS_C_NO_BUFFER, + 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_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 gss_wrap(minor_status, context_handle, + conf_req_flag, (gss_qop_t) qop_req, + input_message_buffer, conf_state, + output_message_buffer); +} + +/* + * It is only possible to implement gss_wrap_size_limit() on top + * of gss_wrap_iov_length() for mechanisms that do not use any + * padding and have fixed length headers/trailers. + */ +static OM_uint32 +gssint_wrap_size_limit_iov_shim(gss_mechanism mech, + 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_iov_buffer_desc iov[4]; + OM_uint32 status; + OM_uint32 ohlen; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[0].buffer.value = NULL; + iov[0].buffer.length = 0; + + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.length = req_output_size; + iov[1].buffer.value = NULL; + + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[2].buffer.value = NULL; + iov[2].buffer.length = 0; + + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[3].buffer.value = NULL; + iov[3].buffer.length = 0; + + assert(mech->gss_wrap_iov_length); + + status = mech->gss_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, + NULL, iov, + sizeof(iov)/sizeof(iov[0])); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + ohlen = iov[0].buffer.length + iov[3].buffer.length; + + if (iov[2].buffer.length == 0 && ohlen < req_output_size) + *max_input_size = req_output_size - ohlen; + else + *max_input_size = 0; + + return GSS_S_COMPLETE; +} + +/* + * 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; + OM_uint32 major_status; + + 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) + major_status = mech->gss_wrap_size_limit(minor_status, + ctx->internal_ctx_id, + conf_req_flag, qop_req, + req_output_size, max_input_size); + else if (mech->gss_wrap_iov_length) + major_status = gssint_wrap_size_limit_iov_shim(mech, minor_status, + ctx->internal_ctx_id, + conf_req_flag, qop_req, + req_output_size, max_input_size); + else + major_status = GSS_S_UNAVAILABLE; + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_set_context_option.c b/krb5-1-7/src/lib/gssapi/mechglue/g_set_context_option.c new file mode 100644 index 000000000..17d9e3bac --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_set_context_option.c @@ -0,0 +1,110 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 routine for gss_set_sec_context_option + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 status, minor; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + gss_ctx_id_t internal_ctx = GSS_C_NO_CONTEXT; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) *context_handle; + if (ctx == NULL) { + mech = gssint_get_mechanism (GSS_C_NO_OID); + } else { + mech = gssint_get_mechanism (ctx->mech_type); + } + + if (mech == NULL || mech->gss_set_sec_context_option == NULL) { + return GSS_S_BAD_MECH; + } + + status = mech->gss_set_sec_context_option(minor_status, + ctx ? &internal_ctx : + &ctx->internal_ctx_id, + desired_object, + value); + if (status == GSS_S_COMPLETE) { + if (ctx == NULL && internal_ctx != GSS_C_NO_CONTEXT) { + /* Allocate a union context handle to wrap new context */ + ctx = (gss_union_ctx_id_t)malloc(sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + gssint_delete_internal_sec_context(&minor, + ctx->mech_type, + &internal_ctx, + GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + status = generic_gss_copy_oid(minor_status, + &mech->mech_type, + &ctx->mech_type); + if (status != GSS_S_COMPLETE) { + gssint_delete_internal_sec_context(&minor, + ctx->mech_type, + &internal_ctx, + GSS_C_NO_BUFFER); + free(ctx); + return status; + } + + ctx->internal_ctx_id = internal_ctx; + *context_handle = (gss_ctx_id_t)ctx; + } + } else + map_error(minor_status, mech); + + return status; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_set_cred_option.c b/krb5-1-7/src/lib/gssapi/mechglue/g_set_cred_option.c new file mode 100644 index 000000000..84d18cdf8 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_set_cred_option.c @@ -0,0 +1,81 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 routine for gssspi_set_cred_option + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gssspi_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + gss_union_cred_t union_cred; + gss_mechanism mech; + int i; + OM_uint32 status; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED; + + *minor_status = 0; + + union_cred = (gss_union_cred_t) cred_handle; + + status = GSS_S_BAD_MECH; + + for (i = 0; i < union_cred->count; i++) { + mech = gssint_get_mechanism(&union_cred->mechs_array[i]); + if (mech == NULL) + continue; + + if (mech->gssspi_set_cred_option == NULL) + continue; + + status = (mech->gssspi_set_cred_option)(minor_status, + union_cred->cred_array[i], + desired_object, + value); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + break; + } + } + + return status; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_sign.c b/krb5-1-7/src/lib/gssapi/mechglue/g_sign.c new file mode 100644 index 000000000..eec0f49b4 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_sign.c @@ -0,0 +1,135 @@ +/* #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_get_mic + */ + +#include "mglueP.h" + +static OM_uint32 +val_get_mic_args( + 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) +{ + + /* 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_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; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_get_mic_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_get_mic) { + status = mech->gss_get_mic( + minor_status, + ctx->internal_ctx_id, + qop_req, + message_buffer, + msg_token); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} + +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; + +{ + return (gss_get_mic(minor_status, context_handle, (gss_qop_t) qop_req, + message_buffer, msg_token)); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_store_cred.c b/krb5-1-7/src/lib/gssapi/mechglue/g_store_cred.c new file mode 100644 index 000000000..1d438c4b9 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_store_cred.c @@ -0,0 +1,186 @@ +/* + * 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 + +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); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + 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); + + major_status = mech->gss_store_cred( + minor_status, + (gss_cred_id_t)mech_cred, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + elements_stored, + cred_usage_stored); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; + } + + /* 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( + 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) { + map_error(minor_status, mech); + 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-7/src/lib/gssapi/mechglue/g_unseal.c b/krb5-1-7/src/lib/gssapi/mechglue/g_unseal.c new file mode 100644 index 000000000..c6b33506b --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_unseal.c @@ -0,0 +1,130 @@ +/* #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_unwrap + */ + +#include "mglueP.h" + +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; + +{ +/* 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_unwrap) { + status = mech->gss_unwrap(minor_status, + ctx->internal_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_unwrap_aead || mech->gss_unwrap_iov) { + status = gssint_unwrap_aead(mech, + minor_status, + ctx, + input_message_buffer, + GSS_C_NO_BUFFER, + output_message_buffer, + conf_state, + (gss_qop_t *)qop_state); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + +/* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +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; + +{ + return (gss_unwrap(minor_status, context_handle, + input_message_buffer, + output_message_buffer, conf_state, (gss_qop_t *) qop_state)); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_aead.c b/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_aead.c new file mode 100644 index 000000000..7dcc27701 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_aead.c @@ -0,0 +1,198 @@ +/* #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_unwrap_aead + */ + +#include "mglueP.h" + +static OM_uint32 +val_unwrap_aead_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 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 (input_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_payload_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + +static OM_uint32 +gssint_unwrap_aead_iov_shim(gss_mechanism mech, + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 status; + gss_iov_buffer_desc iov[3]; + int i = 0; + + iov[i].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[i].buffer = *input_message_buffer; + i++; + + if (input_assoc_buffer != NULL) { + iov[i].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[i].buffer = *input_assoc_buffer; + i++; + } + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + assert(mech->gss_unwrap_iov); + + status = mech->gss_unwrap_iov(minor_status, context_handle, conf_state, + qop_state, iov, i); + if (status == GSS_S_COMPLETE) { + *output_payload_buffer = iov[i - 1].buffer; + } else { + OM_uint32 minor; + + map_error(minor_status, mech); + + if (iov[i - 1].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + gss_release_buffer(&minor, &iov[i - 1].buffer); + iov[i - 1].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } + + return status; +} + +OM_uint32 +gssint_unwrap_aead (gss_mechanism mech, + OM_uint32 *minor_status, + gss_union_ctx_id_t ctx, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 status; + + assert(mech != NULL); + assert(ctx != NULL); + + /* EXPORT DELETE START */ + + if (mech->gss_unwrap_aead) { + status = mech->gss_unwrap_aead(minor_status, + ctx->internal_ctx_id, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_unwrap_iov) { + status = gssint_unwrap_aead_iov_shim(mech, + minor_status, + ctx->internal_ctx_id, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + } else + status = GSS_S_UNAVAILABLE; + /* EXPORT DELETE END */ + + return (status); +} + +OM_uint32 KRB5_CALLCONV +gss_unwrap_aead (minor_status, + context_handle, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t input_message_buffer; +gss_buffer_t input_assoc_buffer; +gss_buffer_t output_payload_buffer; +int *conf_state; +gss_qop_t *qop_state; +{ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_unwrap_aead_args(minor_status, context_handle, + input_message_buffer, input_assoc_buffer, + output_payload_buffer, + conf_state, qop_state); + 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); + + return gssint_unwrap_aead(mech, minor_status, context_handle, + input_message_buffer, input_assoc_buffer, + output_payload_buffer, conf_state, qop_state); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_iov.c b/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_iov.c new file mode 100644 index 000000000..ebef1a70a --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_unwrap_iov.c @@ -0,0 +1,114 @@ +/* #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_unwrap_iov + */ + +#include "mglueP.h" + +static OM_uint32 +val_unwrap_iov_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 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 (iov == GSS_C_NO_IOV_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_unwrap_iov (minor_status, + context_handle, + conf_state, + qop_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int * conf_state; +gss_qop_t *qop_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_unwrap_iov_args(minor_status, context_handle, + conf_state, qop_state, iov, iov_count); + 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_unwrap_iov) { + status = mech->gss_unwrap_iov( + minor_status, + ctx->internal_ctx_id, + conf_state, + qop_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_userok.c b/krb5-1-7/src/lib/gssapi/mechglue/g_userok.c new file mode 100644 index 000000000..90fa90335 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_userok.c @@ -0,0 +1,114 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_userok.c 1.1 04/03/25 SMI" */ + +#include +#include +#include +#include +#include +#include + + +static OM_uint32 +compare_names(OM_uint32 *minor, + const gss_OID mech_type, + const gss_name_t name, + const char *user, + int *user_ok) +{ + + OM_uint32 status, tmpMinor; + gss_name_t imported_name; + gss_name_t canon_name; + gss_buffer_desc gss_user; + int match = 0; + + *user_ok = 0; + + gss_user.value = (void *)user; + if (!gss_user.value || !name || !mech_type) + return (GSS_S_BAD_NAME); + gss_user.length = strlen(gss_user.value); + + status = gss_import_name(minor, + &gss_user, + GSS_C_NT_USER_NAME, + &imported_name); + if (status != GSS_S_COMPLETE) { + goto out; + } + + status = gss_canonicalize_name(minor, + imported_name, + mech_type, + &canon_name); + if (status != GSS_S_COMPLETE) { + (void) gss_release_name(&tmpMinor, &imported_name); + goto out; + } + + status = gss_compare_name(minor, + canon_name, + name, + &match); + (void) gss_release_name(&tmpMinor, &canon_name); + (void) gss_release_name(&tmpMinor, &imported_name); + if (status == GSS_S_COMPLETE) { + if (match) + *user_ok = 1; /* remote user is a-ok */ + } + +out: + return (status); +} + + +OM_uint32 +gssint_userok(OM_uint32 *minor, + const gss_name_t name, + const char *user, + int *user_ok) + +{ + gss_mechanism mech; + gss_union_name_t intName; + gss_name_t mechName = NULL; + OM_uint32 major; + + if (minor == NULL || user_ok == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (name == NULL || user == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + *user_ok = 0; + *minor = GSS_S_COMPLETE; + + intName = (gss_union_name_t)name; + + mech = gssint_get_mechanism(intName->mech_type); + if (mech == NULL) + return (GSS_S_UNAVAILABLE); + + /* may need to import the name if this is not MN */ + if (intName->mech_type == NULL) { + return (GSS_S_FAILURE); + } else + mechName = intName->mech_name; + + if (mech->gssint_userok) { + major = mech->gssint_userok(minor, mechName, + user, user_ok); + if (major != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + major = compare_names(minor, intName->mech_type, + name, user, user_ok); + + return (major); +} /* gss_userok */ + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_verify.c b/krb5-1-7/src/lib/gssapi/mechglue/g_verify.c new file mode 100644 index 000000000..da3279cc7 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_verify.c @@ -0,0 +1,106 @@ +/* #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_mic + */ + +#include "mglueP.h" + +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; + +{ + 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_mic) { + status = mech->gss_verify_mic( + minor_status, + ctx->internal_ctx_id, + message_buffer, + token_buffer, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} + +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; + +{ + return (gss_verify_mic(minor_status, context_handle, + message_buffer, token_buffer, + (gss_qop_t *) qop_state)); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_aead.c b/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_aead.c new file mode 100644 index 000000000..ff170e237 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_aead.c @@ -0,0 +1,267 @@ +/* #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_wrap_aead + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_aead_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 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 (input_payload_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); +} + +static OM_uint32 +gssint_wrap_aead_iov_shim(gss_mechanism mech, + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + gss_iov_buffer_desc iov[5]; + OM_uint32 status; + size_t offset; + int i = 0, iov_count; + + /* HEADER | SIGN_ONLY_DATA | DATA | PADDING | TRAILER */ + + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + if (input_assoc_buffer != GSS_C_NO_BUFFER) { + iov[i].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[i].buffer = *input_assoc_buffer; + i++; + } + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer = *input_payload_buffer; + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + iov_count = i; + + assert(mech->gss_wrap_iov_length); + + status = mech->gss_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, + NULL, iov, iov_count); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + /* Format output token (does not include associated data) */ + for (i = 0, output_message_buffer->length = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + continue; + + output_message_buffer->length += iov[i].buffer.length; + } + + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + i = 0, offset = 0; + + /* HEADER */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + /* SIGN_ONLY_DATA */ + if (input_assoc_buffer != GSS_C_NO_BUFFER) + i++; + + /* DATA */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + + memcpy(iov[i].buffer.value, input_payload_buffer->value, iov[i].buffer.length); + i++; + + /* PADDING */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + /* TRAILER */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + assert(offset == output_message_buffer->length); + + assert(mech->gss_wrap_iov); + + status = mech->gss_wrap_iov(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + if (status != GSS_S_COMPLETE) { + OM_uint32 minor; + + map_error(minor_status, mech); + gss_release_buffer(&minor, output_message_buffer); + } + + return status; +} + +OM_uint32 +gssint_wrap_aead (gss_mechanism mech, + OM_uint32 *minor_status, + gss_union_ctx_id_t ctx, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + /* EXPORT DELETE START */ + OM_uint32 status; + + assert(ctx != NULL); + assert(mech != NULL); + + if (mech->gss_wrap_aead) { + status = mech->gss_wrap_aead(minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_wrap_iov && mech->gss_wrap_iov_length) { + status = gssint_wrap_aead_iov_shim(mech, + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + } else + status = GSS_S_UNAVAILABLE; + + /* EXPORT DELETE END */ + + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_wrap_aead (minor_status, + context_handle, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_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_assoc_buffer; +gss_buffer_t input_payload_buffer; +int * conf_state; +gss_buffer_t output_message_buffer; +{ + OM_uint32 status; + gss_mechanism mech; + gss_union_ctx_id_t ctx; + + status = val_wrap_aead_args(minor_status, context_handle, + conf_req_flag, qop_req, + input_assoc_buffer, input_payload_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) + return (GSS_S_BAD_MECH); + + return gssint_wrap_aead(mech, minor_status, context_handle, + conf_req_flag, qop_req, + input_assoc_buffer, input_payload_buffer, + conf_state, output_message_buffer); +} diff --git a/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_iov.c b/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_iov.c new file mode 100644 index 000000000..8d054b259 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/g_wrap_iov.c @@ -0,0 +1,207 @@ +/* #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_wrap_iov + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_iov_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 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 (iov == GSS_C_NO_IOV_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_wrap_iov (minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int conf_req_flag; +gss_qop_t qop_req; +int * conf_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + 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_wrap_iov) { + status = mech->gss_wrap_iov( + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_wrap_iov_length (minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int conf_req_flag; +gss_qop_t qop_req; +int * conf_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + 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_wrap_iov_length) { + status = mech->gss_wrap_iov_length( + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_release_iov_buffer (minor_status, + iov, + iov_count) +OM_uint32 * minor_status; +gss_iov_buffer_desc * iov; +int iov_count; +{ + OM_uint32 status = GSS_S_COMPLETE; + int i; + + if (minor_status) + *minor_status = 0; + + if (iov == GSS_C_NO_IOV_BUFFER) + return GSS_S_COMPLETE; + + for (i = 0; i < iov_count; i++) { + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + status = gss_release_buffer(minor_status, &iov[i].buffer); + if (status != GSS_S_COMPLETE) + break; + + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } + + return status; +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/gssd_pname_to_uid.c b/krb5-1-7/src/lib/gssapi/mechglue/gssd_pname_to_uid.c new file mode 100644 index 000000000..c310f1630 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/gssd_pname_to_uid.c @@ -0,0 +1,67 @@ +/* #pragma ident "@(#)gssd_pname_to_uid.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 routines that test the mech id either passed in to + * gss_init_sec_contex() or gss_accept_sec_context() or within the glue + * routine supported version of the security context and then call + * the appropriate underlying mechanism library procedure. + * + */ + +#include "mglueP.h" + +int gssd_pname_to_uid(pname, name_type, mech_type, uid) + +char * pname; +gss_OID name_type; +gss_OID mech_type; +uid_t * uid; +{ + int status; + gss_mechanism mech; + + /* + * find the appropriate mechanism specific pname_to_uid procedure and + * call it. + */ + + mech = gssint_get_mechanism (mech_type); + + if (mech) { + if (mech_type == GSS_C_NULL_OID) + mech_type = &mech->mech_type; + + if (mech->pname_to_uid) { + status = mech->pname_to_uid(pname, name_type, mech_type, uid); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_BAD_MECH; + } else + status = GSS_S_BAD_MECH; + + return(status); +} + diff --git a/krb5-1-7/src/lib/gssapi/mechglue/mechglue.h b/krb5-1-7/src/lib/gssapi/mechglue/mechglue.h new file mode 100644 index 000000000..7f3334aec --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/mechglue.h @@ -0,0 +1,42 @@ +/* #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 Extension functions -- these functions aren't */ +/* in the GSSAPI, but they are provided in this library */ + +#include + +void KRB5_CALLCONV gss_initialize(void); + +#endif /* _GSS_MECHGLUE_H */ diff --git a/krb5-1-7/src/lib/gssapi/mechglue/mglueP.h b/krb5-1-7/src/lib/gssapi/mechglue/mglueP.h new file mode 100644 index 000000000..001636146 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/mechglue/mglueP.h @@ -0,0 +1,661 @@ +/* #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) + +/* + * 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; + +typedef OM_uint32 (*gss_acquire_cred_with_password_sfct)( + void *, /* context */ + OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + const gss_buffer_t, /* password */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + int, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + /* */); + +/* + * 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 */ +int gssint_mechglue_initialize_library(void); + +OM_uint32 gssint_get_mech_type_oid(gss_OID OID, gss_buffer_t token); + +/* + * 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 { + gss_OID_desc mech_type; + void * context; + OM_uint32 (*gss_acquire_cred) + ( + 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) + ( + OM_uint32*, /* minor_status */ + gss_cred_id_t* /* cred_handle */ + ); + OM_uint32 (*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 (*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 (*gss_process_context_token) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t /* token_buffer */ + ); + OM_uint32 (*gss_delete_sec_context) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_buffer_t /* output_token */ + ); + OM_uint32 (*gss_context_time) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + OM_uint32* /* time_rec */ + ); + OM_uint32 (*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 (*gss_verify_mic) + ( + 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 (*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 (*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 (*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 (*gss_indicate_mechs) + ( + OM_uint32*, /* minor_status */ + gss_OID_set* /* mech_set */ + ); + OM_uint32 (*gss_compare_name) + ( + OM_uint32*, /* minor_status */ + gss_name_t, /* name1 */ + gss_name_t, /* name2 */ + int* /* name_equal */ + ); + OM_uint32 (*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 (*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 (*gss_release_name) + ( + OM_uint32*, /* minor_status */ + gss_name_t* /* input_name */ + ); + OM_uint32 (*gss_inquire_cred) + ( + 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) + ( + 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) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* interprocess_token */ + ); + OM_uint32 (*gss_import_sec_context) + ( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ + ); + OM_uint32 (*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 (*gss_inquire_names_for_mech) + ( + OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ + ); + OM_uint32 (*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 */ + ); + OM_uint32 (*gss_internal_release_oid) + ( + OM_uint32 *, /* minor_status */ + gss_OID * /* OID */ + ); + OM_uint32 (*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 */ + ); +#if 0 + int (*pname_to_uid) + ( + char *, /* pname */ + gss_OID, /* name type */ + gss_OID, /* mech type */ + uid_t * /* uid */ + ); + OM_uint32 (*gssint_userok) + ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* pname */ + const char *, /* local user */ + int * /* user ok? */ + /* */); +#endif + OM_uint32 (*gss_export_name) + ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t /* exported_name */ + /* */); + OM_uint32 (*gss_store_cred) + ( + 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 */ + /* */); + + + /* GGF extensions */ + + OM_uint32 (*gss_inquire_sec_context_by_oid) + ( + OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_OID, /* OID */ + gss_buffer_set_t * /* data_set */ + ); + OM_uint32 (*gss_inquire_cred_by_oid) + ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* cred_handle */ + const gss_OID, /* OID */ + gss_buffer_set_t * /* data_set */ + ); + OM_uint32 (*gss_set_sec_context_option) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + const gss_OID, /* OID */ + const gss_buffer_t /* value */ + ); + OM_uint32 (*gssspi_set_cred_option) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + const gss_OID, /* OID */ + const gss_buffer_t /* value */ + ); + OM_uint32 (*gssspi_mech_invoke) + ( + OM_uint32*, /* minor_status */ + const gss_OID, /* mech OID */ + const gss_OID, /* OID */ + gss_buffer_t /* value */ + ); + + /* AEAD extensions */ + OM_uint32 (*gss_wrap_aead) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* input_payload_buffer */ + int *, /* conf_state */ + gss_buffer_t /* output_message_buffer */ + /* */); + + OM_uint32 (*gss_unwrap_aead) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* output_payload_buffer */ + int *, /* conf_state */ + gss_qop_t * /* qop_state */ + /* */); + + /* SSPI extensions */ + OM_uint32 (*gss_wrap_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (*gss_unwrap_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (*gss_wrap_iov_length) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag*/ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (*gss_complete_auth_token) + ( + OM_uint32*, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + gss_buffer_t /* input_message_buffer */ + ); + +} *gss_mechanism; + +/* This structure MUST NOT be used by any code outside libgss */ +typedef struct gss_config_ext { + gss_acquire_cred_with_password_sfct gss_acquire_cred_with_password; +} *gss_mechanism_ext; + +/* + * 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 */ + gss_mechanism_ext mech_ext; /* extensions */ + int priority; /* mechanism preference order */ + int freeMech; /* free mech table */ + struct gss_mech_config *next; /* next element in the list */ +} *gss_mech_info; + +/********************************************************/ +/* Internal mechglue routines */ + +#if 0 +int gssint_mechglue_init(void); +void gssint_mechglue_fini(void); +#endif + +gss_mechanism gssint_get_mechanism (gss_OID); +gss_mechanism_ext gssint_get_mechanism_ext(const 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_delete_internal_sec_context (OM_uint32 *, gss_OID, + gss_ctx_id_t *, gss_buffer_t); +#ifdef _GSS_STATIC_LINK +int gssint_register_mechinfo(gss_mech_info template); +#endif + +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 * const, /* 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 +gssint_userok( + OM_uint32 *, /* minor */ + const gss_name_t, /* name */ + const char *, /* user */ + int * /* user_ok */ +); + +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 */ +); + +OM_uint32 +gssint_wrap_aead (gss_mechanism, /* mech */ + OM_uint32 *, /* minor_status */ + gss_union_ctx_id_t, /* ctx */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req_flag */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* input_payload_buffer */ + int *, /* conf_state */ + gss_buffer_t); /* output_message_buffer */ +OM_uint32 +gssint_unwrap_aead (gss_mechanism, /* mech */ + OM_uint32 *, /* minor_status */ + gss_union_ctx_id_t, /* ctx */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* output_payload_buffer */ + int *, /* conf_state */ + gss_qop_t *); /* qop_state */ + + +/* Use this to map an error code that was returned from a mech + operation; the mech will be asked to produce the associated error + messages. + + Remember that if the minor status code cannot be returned to the + caller (e.g., if it's stuffed in an automatic variable and then + ignored), then we don't care about producing a mapping. */ +#define map_error(MINORP, MECH) \ + (*(MINORP) = gssint_mecherrmap_map(*(MINORP), &(MECH)->mech_type)) +#define map_error_oid(MINORP, MECHOID) \ + (*(MINORP) = gssint_mecherrmap_map(*(MINORP), (MECHOID))) + +/* Use this to map an errno value or com_err error code being + generated within the mechglue code (e.g., by calling generic oid + ops). Any errno or com_err values produced by mech operations + should be processed with map_error. This means they'll be stored + separately even if the mech uses com_err, because we can't assume + that it will use com_err. */ +#define map_errcode(MINORP) \ + (*(MINORP) = gssint_mecherrmap_map_errcode(*(MINORP))) + +#endif /* _GSS_MECHGLUEP_H */ diff --git a/krb5-1-7/src/lib/gssapi/spnego/Makefile.in b/krb5-1-7/src/lib/gssapi/spnego/Makefile.in new file mode 100644 index 000000000..95bfd1ab1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/spnego/Makefile.in @@ -0,0 +1,26 @@ +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 +DEFS=-D_GSS_STATIC_LINK=1 + +##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@ diff --git a/krb5-1-7/src/lib/gssapi/spnego/deps b/krb5-1-7/src/lib/gssapi/spnego/deps new file mode 100644 index 000000000..2d3c30cf1 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/spnego/deps @@ -0,0 +1,17 @@ +# +# Generated makefile dependencies follow. +# +spnego_mech.so spnego_mech.po $(OUTPRE)spnego_mech.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_ext.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-7/src/lib/gssapi/spnego/gssapiP_spnego.h b/krb5-1-7/src/lib/gssapi/spnego/gssapiP_spnego.h new file mode 100644 index 000000000..33c936549 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/spnego/gssapiP_spnego.h @@ -0,0 +1,427 @@ +/* + * 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 +#include + +#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 +#define GENERAL_STRING 0x1b + +/* + * 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 declarations */ +extern const gss_OID_desc * const gss_mech_spnego; +extern const gss_OID_set_desc * const gss_mech_set_spnego; + +#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 +( + 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 +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + gss_cred_id_t * /* cred_handle */ +); + +OM_uint32 spnego_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 */ +); + +#ifndef LEAN_CLIENT +OM_uint32 spnego_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 */ + /* CSTYLED */ + gss_cred_id_t * /* delegated_cred_handle */ +); +#endif /* LEAN_CLIENT */ + +OM_uint32 spnego_gss_compare_name +( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* name1 */ + const gss_name_t, /* name2 */ + int * /* name_equal */ +); + +OM_uint32 spnego_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 spnego_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 spnego_gss_import_name +( + 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 +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + gss_name_t * /* input_name */ +); + +OM_uint32 spnego_gss_inquire_names_for_mech +( + OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ +); + +OM_uint32 spnego_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 spnego_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 spnego_gss_process_context_token +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer +); + +OM_uint32 spnego_gss_delete_sec_context +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token +); + +OM_uint32 spnego_gss_context_time +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec +); +#ifndef LEAN_CLIENT +OM_uint32 spnego_gss_export_sec_context +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token +); + +OM_uint32 spnego_gss_import_sec_context +( + OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle +); +#endif /* LEAN_CLIENT */ + +OM_uint32 spnego_gss_inquire_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 *opened +); + +OM_uint32 spnego_gss_wrap_size_limit +( + 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_get_mic +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token +); + +OM_uint32 spnego_gss_verify_mic +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t msg_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state +); + +OM_uint32 +spnego_gss_inquire_sec_context_by_oid +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set +); + +OM_uint32 +spnego_gss_set_cred_option +( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_object, + const gss_buffer_t value +); + +OM_uint32 +spnego_gss_set_sec_context_option +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value +); + +#ifdef _GSS_STATIC_LINK +int gss_spnegoint_lib_init(void); +void gss_spnegoint_lib_fini(void); +#else +gss_mechanism KRB5_CALLCONV gss_mech_initialize(void); +#endif /* _GSS_STATIC_LINK */ + +OM_uint32 spnego_gss_wrap_aead +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer +); + +OM_uint32 spnego_gss_unwrap_aead +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state +); + +OM_uint32 spnego_gss_wrap_iov +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 spnego_gss_unwrap_iov +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 spnego_gss_wrap_iov_length +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 +spnego_gss_complete_auth_token +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer +); + +#ifdef __cplusplus +} +#endif + +#endif /* _GSSAPIP_SPNEGO_H_ */ diff --git a/krb5-1-7/src/lib/gssapi/spnego/mech_spnego.exports b/krb5-1-7/src/lib/gssapi/spnego/mech_spnego.exports new file mode 100644 index 000000000..9d570e5c0 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/spnego/mech_spnego.exports @@ -0,0 +1 @@ +gss_mech_initialize diff --git a/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c b/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c new file mode 100644 index 000000000..8235b5bc2 --- /dev/null +++ b/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c @@ -0,0 +1,3459 @@ +/* + * Copyright (C) 2006,2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + * + */ +/* + * Copyright (c) 2006-2008, 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. + */ +/* #pragma ident "@(#)spnego_mech.c 1.7 04/09/28 SMI" */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gssapiP_spnego.h" +#include + + +#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, unsigned int*); +extern int gssint_put_der_length(OM_uint32, unsigned char **, unsigned int); + + +/* 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_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, + int, + 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 *); + +static int +is_kerb_mech(gss_OID oid); + +/* 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; + +static int make_NegHints(OM_uint32 *, gss_cred_id_t, gss_buffer_t *); +static int put_neg_hints(unsigned char **, gss_buffer_t, unsigned int); +static OM_uint32 +acc_ctx_hints(OM_uint32 *, gss_ctx_id_t *, gss_cred_id_t, + gss_buffer_t *, OM_uint32 *, send_token_flag *); + +/* + * 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 = +{ + {SPNEGO_OID_LENGTH, SPNEGO_OID}, + NULL, + spnego_gss_acquire_cred, + spnego_gss_release_cred, + spnego_gss_init_sec_context, +#ifndef LEAN_CLIENT + spnego_gss_accept_sec_context, +#else + NULL, +#endif /* LEAN_CLIENT */ + NULL, /* gss_process_context_token */ + spnego_gss_delete_sec_context, /* gss_delete_sec_context */ + spnego_gss_context_time, /* gss_context_time */ + spnego_gss_get_mic, /* gss_get_mic */ + spnego_gss_verify_mic, /* gss_verify_mic */ + spnego_gss_wrap, /* gss_wrap */ + spnego_gss_unwrap, /* gss_unwrap */ + spnego_gss_display_status, + NULL, /* gss_indicate_mechs */ + spnego_gss_compare_name, + spnego_gss_display_name, + spnego_gss_import_name, + spnego_gss_release_name, + NULL, /* gss_inquire_cred */ + NULL, /* gss_add_cred */ +#ifndef LEAN_CLIENT + spnego_gss_export_sec_context, /* gss_export_sec_context */ + spnego_gss_import_sec_context, /* gss_import_sec_context */ +#else + NULL, /* gss_export_sec_context */ + NULL, /* gss_import_sec_context */ +#endif /* LEAN_CLIENT */ + 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 */ + spnego_gss_inquire_sec_context_by_oid, /* gss_inquire_sec_context_by_oid */ + NULL, /* gss_inquire_cred_by_oid */ + spnego_gss_set_sec_context_option, /* gss_set_sec_context_option */ + spnego_gss_set_cred_option, /* gssspi_set_cred_option */ + NULL, /* gssspi_mech_invoke */ + spnego_gss_wrap_aead, + spnego_gss_unwrap_aead, + spnego_gss_wrap_iov, + spnego_gss_unwrap_iov, + spnego_gss_wrap_iov_length, + spnego_gss_complete_auth_token +}; + +#ifdef _GSS_STATIC_LINK +#include "mglueP.h" + +static int gss_spnegomechglue_init(void) +{ + struct gss_mech_config mech_spnego; + + memset(&mech_spnego, 0, sizeof(mech_spnego)); + mech_spnego.mech = &spnego_mechanism; + mech_spnego.mechNameStr = "spnego"; + mech_spnego.mech_type = GSS_C_NO_OID; + + return gssint_register_mechinfo(&mech_spnego); +} +#else +gss_mechanism KRB5_CALLCONV +gss_mech_initialize(void) +{ + return (&spnego_mechanism); +} + +MAKE_INIT_FUNCTION(gss_krb5int_lib_init); +MAKE_FINI_FUNCTION(gss_krb5int_lib_fini); +int gss_krb5int_lib_init(void); +#endif /* _GSS_STATIC_LINK */ + +int gss_spnegoint_lib_init(void) +{ +#ifdef _GSS_STATIC_LINK + return gss_spnegomechglue_init(); +#else + return 0; +#endif +} + +void gss_spnegoint_lib_fini(void) +{ +} + +/*ARGSUSED*/ +OM_uint32 +spnego_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 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(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) { + map_errcode(minor_status); + 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; + map_errcode(minor_status); + *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 if (sc->mic_reqd && + (sc->ctx_flags & GSS_C_INTEG_FLAG)) { + *negState = ACCEPT_INCOMPLETE; + *tokflag = CONT_TOKEN_SEND; + ret = GSS_S_CONTINUE_NEEDED; + } else { + *negState = ACCEPT_COMPLETE; + *tokflag = NO_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } +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; + map_errcode(minor_status); + return GSS_S_DEFECTIVE_TOKEN; + } + if (acc_negState == ACCEPT_DEFECTIVE_TOKEN) { + *minor_status = ERR_SPNEGO_NEGOTIATION_FAILED; + map_errcode(minor_status); + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * If the mechanism we sent is not the mechanism returned from + * the server, we need to handle the server's counter + * proposal. There is a bug in SAMBA servers that always send + * the old Kerberos mech OID, even though we sent the new one. + * So we will treat all the Kerberos mech OIDS as the same. + */ + if (!(is_kerb_mech(supportedMech) && + is_kerb_mech(sc->internal_mech)) && + !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; + map_errcode(minor_status); + 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) { + map_errcode(minor_status); + 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 && + mechtok_out->length == 0 && + (!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( + 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, + 0, + 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; + if (ret_flags != NULL) + *ret_flags = spnego_ctx->ctx_flags; + 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 */ + +/* We don't want to import KRB5 headers here */ +static const gss_OID_desc gss_mech_krb5_oid = + { 9, "\052\206\110\206\367\022\001\002\002" }; +static const gss_OID_desc gss_mech_krb5_wrong_oid = + { 9, "\052\206\110\202\367\022\001\002\002" }; + +/* + * 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 a sequence + * and place in buf_out, advancing buf_out. + */ + +static int +put_neg_hints(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)++ = SEQUENCE; + 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); +} + +/* + * NegHints ::= SEQUENCE { + * hintName [0] GeneralString OPTIONAL, + * hintAddress [1] OCTET STRING OPTIONAL + * } + */ + +#define HOST_PREFIX "host@" +#define HOST_PREFIX_LEN (sizeof(HOST_PREFIX) - 1) + +static int +make_NegHints(OM_uint32 *minor_status, + gss_cred_id_t cred, gss_buffer_t *outbuf) +{ + gss_buffer_desc hintNameBuf; + gss_name_t hintName = GSS_C_NO_NAME; + gss_name_t hintKerberosName; + gss_OID hintNameType; + OM_uint32 major_status; + OM_uint32 minor; + unsigned int tlen = 0; + unsigned int hintNameSize = 0; + unsigned int negHintsSize = 0; + unsigned char *ptr; + unsigned char *t; + + *outbuf = GSS_C_NO_BUFFER; + + if (cred != GSS_C_NO_CREDENTIAL) { + major_status = gss_inquire_cred(minor_status, + cred, + &hintName, + NULL, + NULL, + NULL); + if (major_status != GSS_S_COMPLETE) + return (major_status); + } + + if (hintName == GSS_C_NO_NAME) { + krb5_error_code code; + krb5int_access kaccess; + char hostname[HOST_PREFIX_LEN + MAXHOSTNAMELEN + 1] = HOST_PREFIX; + + code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION); + if (code != 0) { + *minor_status = code; + return (GSS_S_FAILURE); + } + + /* this breaks mutual authentication but Samba relies on it */ + code = (*kaccess.clean_hostname)(NULL, NULL, + &hostname[HOST_PREFIX_LEN], + MAXHOSTNAMELEN); + if (code != 0) { + *minor_status = code; + return (GSS_S_FAILURE); + } + + hintNameBuf.value = hostname; + hintNameBuf.length = strlen(hostname); + + major_status = gss_import_name(minor_status, + &hintNameBuf, + GSS_C_NT_HOSTBASED_SERVICE, + &hintName); + if (major_status != GSS_S_COMPLETE) { + return (major_status); + } + } + + hintNameBuf.value = NULL; + hintNameBuf.length = 0; + + major_status = gss_canonicalize_name(minor_status, + hintName, + (gss_OID)&gss_mech_krb5_oid, + &hintKerberosName); + if (major_status != GSS_S_COMPLETE) { + gss_release_name(&minor, &hintName); + return (major_status); + } + gss_release_name(&minor, &hintName); + + major_status = gss_display_name(minor_status, + hintKerberosName, + &hintNameBuf, + &hintNameType); + if (major_status != GSS_S_COMPLETE) { + gss_release_name(&minor, &hintName); + return (major_status); + } + gss_release_name(&minor, &hintKerberosName); + + /* + * Now encode the name hint into a NegHints ASN.1 type + */ + major_status = GSS_S_FAILURE; + + /* Length of DER encoded GeneralString */ + tlen = 1 + gssint_der_length_size(hintNameBuf.length) + + hintNameBuf.length; + hintNameSize = tlen; + + /* Length of DER encoded hintName */ + tlen += 1 + gssint_der_length_size(hintNameSize); + negHintsSize = tlen; + + t = (unsigned char *)malloc(tlen); + if (t == NULL) { + *minor_status = ENOMEM; + goto errout; + } + + ptr = t; + + *ptr++ = CONTEXT | 0x00; /* hintName identifier */ + if (gssint_put_der_length(hintNameSize, + &ptr, tlen - (int)(ptr-t))) + goto errout; + + *ptr++ = GENERAL_STRING; + if (gssint_put_der_length(hintNameBuf.length, + &ptr, tlen - (int)(ptr-t))) + goto errout; + + memcpy(ptr, hintNameBuf.value, hintNameBuf.length); + ptr += hintNameBuf.length; + + *outbuf = (gss_buffer_t)malloc(sizeof(gss_buffer_desc)); + if (*outbuf == NULL) { + *minor_status = ENOMEM; + goto errout; + } + (*outbuf)->value = (void *)t; + (*outbuf)->length = ptr - t; + + t = NULL; /* don't free */ + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + +errout: + if (t != NULL) { + free(t); + } + + gss_release_buffer(&minor, &hintNameBuf); + + return (major_status); +} + +static OM_uint32 +acc_ctx_hints(OM_uint32 *minor_status, + gss_ctx_id_t *ctx, + gss_cred_id_t cred, + gss_buffer_t *mechListMIC, + OM_uint32 *negState, + send_token_flag *return_token) +{ + OM_uint32 tmpmin, ret; + gss_OID_set supported_mechSet; + spnego_gss_ctx_id_t sc = NULL; + + *mechListMIC = GSS_C_NO_BUFFER; + supported_mechSet = GSS_C_NO_OID_SET; + *return_token = ERROR_TOKEN_SEND; + *negState = REJECT; + *minor_status = 0; + + *ctx = GSS_C_NO_CONTEXT; + ret = GSS_S_DEFECTIVE_TOKEN; + + 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; + } + } + + ret = make_NegHints(minor_status, cred, mechListMIC); + 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. + */ + sc = create_spnego_ctx(); + if (sc == NULL) { + ret = GSS_S_FAILURE; + *return_token = NO_TOKEN_SEND; + goto cleanup; + } + if (put_mech_set(supported_mechSet, &sc->DER_mechTypes) < 0) { + ret = GSS_S_FAILURE; + *return_token = NO_TOKEN_SEND; + goto cleanup; + } + sc->internal_mech = GSS_C_NO_OID; + + *negState = ACCEPT_INCOMPLETE; + *return_token = INIT_TOKEN_SEND; + sc->firstpass = 1; + *ctx = (gss_ctx_id_t)sc; + ret = GSS_S_COMPLETE; + +cleanup: + gss_release_oid_set(&tmpmin, &supported_mechSet); + + return ret; +} + +/* + * 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 = (spnego_gss_ctx_id_t)*ctx; + if (sc != NULL) { + gss_release_buffer(&tmpmin, &sc->DER_mechTypes); + assert(mech_wanted != GSS_C_NO_OID); + } else + 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; + map_errcode(minor_status); + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + return GSS_S_BAD_MECH; + } + ret = mech->gss_indicate_mechs(minor_status, &mech_set); + if (ret != GSS_S_COMPLETE) { + *tokflag = NO_TOKEN_SEND; + map_error(minor_status, mech); + 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; + map_errcode(minor_status); + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + ret = GSS_S_BAD_MECH; + } +cleanup: + gss_release_oid_set(&tmpmin, &mech_set); + return ret; +} +#ifndef LEAN_CLIENT +/* + * 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; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) { + /* + * 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( + 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, 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; + int sendTokenInit = 0; + + 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; + + sc = (spnego_gss_ctx_id_t)*context_handle; + if (sc == NULL || sc->internal_mech == GSS_C_NO_OID) { + 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; + if (input_token->length == 0) { + sendTokenInit = 1; + ret = acc_ctx_hints(minor_status, + context_handle, + verifier_cred_handle, + &mic_out, + &negState, + &return_token); + if (ret != GSS_S_COMPLETE) + goto cleanup; + ret = GSS_S_CONTINUE_NEEDED; + } else { + /* 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) { + /* For acceptor-sends-first send a tokenInit */ + int tmpret; + + assert(sc != NULL); + + if (sendTokenInit) { + tmpret = make_spnego_tokenInit_msg(sc, + 1, + mic_out, + 0, + GSS_C_NO_BUFFER, + return_token, + output_token); + } else { + tmpret = make_spnego_tokenTarg_msg(negState, + sc ? sc->internal_mech : GSS_C_NO_OID, + &mechtok_out, mic_out, + return_token, + output_token); + } + if (tmpret < 0) + ret = GSS_S_FAILURE; + } + 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); + } else if (ret != GSS_S_CONTINUE_NEEDED) { + if (sc != NULL) { + gss_delete_sec_context(&tmpmin, &sc->ctx_handle, + GSS_C_NO_BUFFER); + release_spnego_ctx(&sc); + } + *context_handle = GSS_C_NO_CONTEXT; + } + 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; +} +#endif /* LEAN_CLIENT */ + + +/*ARGSUSED*/ +OM_uint32 +spnego_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) +{ + 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( + 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( + 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_compare_name( + OM_uint32 *minor_status, + const gss_name_t name1, + const gss_name_t name2, + int *name_equal) +{ + OM_uint32 status = GSS_S_COMPLETE; + dsyslog("Entering compare_name\n"); + + status = gss_compare_name(minor_status, name1, name2, name_equal); + + dsyslog("Leaving compare_name\n"); + return (status); +} + +/*ARGSUSED*/ +/*ARGSUSED*/ +OM_uint32 +spnego_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 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( + 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_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 ret; + ret = gss_unwrap(minor_status, + context_handle, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); + + return (ret); +} + +OM_uint32 +spnego_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 ret; + ret = gss_wrap(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( + 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( + 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( + 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); +} +#ifndef LEAN_CLIENT +OM_uint32 +spnego_gss_export_sec_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( + 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); +} +#endif /* LEAN_CLIENT */ + +OM_uint32 +spnego_gss_inquire_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 *opened) +{ + 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, + opened); + + return (ret); +} + +OM_uint32 +spnego_gss_wrap_size_limit( + 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_get_mic( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + OM_uint32 ret; + ret = gss_get_mic(minor_status, + context_handle, + qop_req, + message_buffer, + message_token); + return (ret); +} + +OM_uint32 +spnego_gss_verify_mic( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t msg_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + OM_uint32 ret; + ret = gss_verify_mic(minor_status, + context_handle, + msg_buffer, + token_buffer, + qop_state); + return (ret); +} + +OM_uint32 +spnego_gss_inquire_sec_context_by_oid( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 ret; + ret = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + desired_object, + data_set); + return (ret); +} + +OM_uint32 +spnego_gss_set_cred_option( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 ret; + ret = gssspi_set_cred_option(minor_status, + cred_handle, + desired_object, + value); + return (ret); +} + +OM_uint32 +spnego_gss_set_sec_context_option( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 ret; + ret = gss_set_sec_context_option(minor_status, + context_handle, + desired_object, + value); + return (ret); +} + +OM_uint32 +spnego_gss_wrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + OM_uint32 ret; + ret = gss_wrap_aead(minor_status, + context_handle, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + + return (ret); +} + +OM_uint32 +spnego_gss_unwrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 ret; + ret = gss_unwrap_aead(minor_status, + context_handle, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + return (ret); +} + +OM_uint32 +spnego_gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + ret = gss_wrap_iov(minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + return (ret); +} + +OM_uint32 +spnego_gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + ret = gss_unwrap_iov(minor_status, + context_handle, + conf_state, + qop_state, + iov, + iov_count); + return (ret); +} + +OM_uint32 +spnego_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + ret = gss_wrap_iov_length(minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + return (ret); +} + + +OM_uint32 +spnego_gss_complete_auth_token( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + OM_uint32 ret; + ret = gss_complete_auth_token(minor_status, + context_handle, + input_message_buffer); + 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) +{ + unsigned int i; + int found = 0; + OM_uint32 major_status = GSS_S_COMPLETE, tmpmin; + gss_OID_set mechs, goodmechs; + + major_status = gss_indicate_mechs(minor_status, &mechs); + + if (major_status != GSS_S_COMPLETE) { + return (major_status); + } + + major_status = gss_create_empty_oid_set(minor_status, rmechs); + + if (major_status != GSS_S_COMPLETE) { + (void) gss_release_oid_set(minor_status, &mechs); + return (major_status); + } + + for (i = 0; i < mechs->count && major_status == 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)) { + + major_status = gss_add_oid_set_member(minor_status, + &mechs->elements[i], + rmechs); + if (major_status == 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 && major_status == GSS_S_COMPLETE && creds != NULL) { + major_status = 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 (major_status == 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 || major_status != GSS_S_COMPLETE) { + *minor_status = ERR_SPNEGO_NO_MECHS_AVAILABLE; + map_errcode(minor_status); + if (major_status == GSS_S_COMPLETE) + major_status = GSS_S_FAILURE; + } + + return (major_status); +} + +/* 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) { + map_errcode(minor_status); + 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 len; + + if (g_get_tag_and_length(buff_in, OCTET_STRING, buff_length, &len) < 0) + return (NULL); + + input_token = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); + if (input_token == NULL) + return (NULL); + + input_token->length = len; + 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; + int length; + unsigned int 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); + if (length < 0 || buff_length - bytes < (unsigned int)length) + return NULL; + + 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 < (unsigned int)length; i++) { + gss_OID_desc *temp = get_mech_oid(minor_status, buff_in, + buff_length - (*buff_in - start)); + if (temp == NULL) + break; + + 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; + if (generic_gss_release_oid(minor_status, &temp)) + map_errcode(minor_status); + } + } + + return (returned_mechSet); +} + +/* + * Encode mechSet into buf. + */ +static int +put_mech_set(gss_OID_set mechSet, gss_buffer_t buf) +{ + unsigned char *ptr; + unsigned 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); +} + +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; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + *minor_status = g_verify_neg_token_init(&ptr, REMAIN); + if (*minor_status) { + map_errcode(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 || REMAIN < (unsigned int)tmplen) + 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 || REMAIN < (unsigned int)tmplen) + 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 || REMAIN < (unsigned int)tmplen) + 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 || REMAIN < (unsigned int)tmplen) + 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 || REMAIN < (unsigned int)tmplen) + 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; + unsigned int i; + + for (i = 0; i < mechset->count; i++) { + gss_OID mech_oid = &mechset->elements[i]; + + /* Accept wrong mechanism OID from MS clients */ + if (mech_oid->length == gss_mech_krb5_wrong_oid.length && + memcmp(mech_oid->elements, gss_mech_krb5_wrong_oid.elements, mech_oid->length) == 0) + mech_oid = (gss_OID)&gss_mech_krb5_oid;; + + gss_test_oid_set_member(minor_status, mech_oid, 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; + map_errcode(minor_status); + 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) +{ + return (spnego_token_t)strdup(name); +} + +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, + int negHintsCompat, + 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; + + /* + * 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 | 0x00; /* 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 (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 (negHintsCompat) { + ret = put_neg_hints(&ptr, mechListMIC, + tlen - (int)(ptr - t)); + if (ret) + goto errout; + } else 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); + if (sendtoken == INIT_TOKEN_SEND && mech_wanted == GSS_C_NO_OID) + 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 ((unsigned int)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); +} + +/* + * Return non-zero if the oid is one of the kerberos mech oids, + * otherwise return zero. + * + * N.B. There are 3 oids that represent the kerberos mech: + * RFC-specified GSS_MECH_KRB5_OID, + * Old pre-RFC GSS_MECH_KRB5_OLD_OID, + * Incorrect MS GSS_MECH_KRB5_WRONG_OID + */ + +static int +is_kerb_mech(gss_OID oid) +{ + int answer = 0; + OM_uint32 minor; + extern const gss_OID_set_desc * const gss_mech_set_krb5_both; + + (void) gss_test_oid_set_member(&minor, + oid, (gss_OID_set)gss_mech_set_krb5_both, &answer); + + return (answer); +} diff --git a/krb5-1-7/src/lib/gssapi32.def b/krb5-1-7/src/lib/gssapi32.def new file mode 100644 index 000000000..fa36f51ed --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/Makefile.in b/krb5-1-7/src/lib/kadm5/Makefile.in new file mode 100644 index 000000000..4644937fe --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/Makefile.in @@ -0,0 +1,107 @@ +thisconfigdir=../.. +myfulldir=lib/kadm5 +mydir=lib/kadm5 +BUILDTOP=$(REL)..$(S).. +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:: + +install-headers-unix install:: $(BUILD_HDRS) + $(INSTALL_DATA) $(srcdir)/admin.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)admin.h + $(INSTALL_DATA) chpass_util_strings.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)chpass_util_strings.h + $(INSTALL_DATA) kadm_err.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)kadm_err.h + +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/kadm5/adb.h b/krb5-1-7/src/lib/kadm5/adb.h new file mode 100644 index 000000000..dce62abb4 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/adb.h @@ -0,0 +1,134 @@ +/* + * 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 +#include +#include "k5-int.h" +#include +#include +#include +#include +#include + +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_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_policy(osa_adb_policy_t *db, + kadm5_config_params *rparams); +osa_adb_ret_t osa_adb_close_policy(osa_adb_policy_t db); +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_policy(osa_adb_policy_t db, + kadm5_policy_t name); +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_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); +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-7/src/lib/kadm5/admin.h b/krb5-1-7/src/lib/kadm5/admin.h new file mode 100644 index 000000000..57e2586f2 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/admin.h @@ -0,0 +1,807 @@ +/* + * lib/kadm5/admin.h + * + * Copyright 2001, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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$ + */ + +/* + * This API is not considered as stable as the main krb5 API. + * + * - We may make arbitrary incompatible changes between feature + * releases (e.g. from 1.7 to 1.8). + * - We will make some effort to avoid making incompatible changes for + * bugfix releases, but will make them if necessary. + * - We make no commitments at all regarding the v1 API (obtained by + * defining USE_KADM5_API_VERSION to 1) and expect to remove it. + */ + +#ifndef __KADM5_ADMIN_H__ +#define __KADM5_ADMIN_H__ + +#if !defined(USE_KADM5_API_VERSION) +#define USE_KADM5_API_VERSION 2 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KADM5INT_BEGIN_DECLS +#if defined(__cplusplus) +#define KADM5INT_BEGIN_DECLS extern "C" { +#define KADM5INT_END_DECLS } +#else +#define KADM5INT_BEGIN_DECLS +#define KADM5INT_END_DECLS +#endif +#endif + +KADM5INT_BEGIN_DECLS + +#define KADM5_ADMIN_SERVICE "kadmin/admin" +#define KADM5_CHANGEPW_SERVICE "kadmin/changepw" +#define KADM5_HIST_PRINCIPAL "kadmin/history" +#define KADM5_KIPROP_HOST_SERVICE "kiprop" + +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 0x00000001 +#define KADM5_CONFIG_DBNAME 0x00000002 +#define KADM5_CONFIG_MKEY_NAME 0x00000004 +#define KADM5_CONFIG_MAX_LIFE 0x00000008 +#define KADM5_CONFIG_MAX_RLIFE 0x00000010 +#define KADM5_CONFIG_EXPIRATION 0x00000020 +#define KADM5_CONFIG_FLAGS 0x00000040 +#define KADM5_CONFIG_ADMIN_KEYTAB 0x00000080 +#define KADM5_CONFIG_STASH_FILE 0x00000100 +#define KADM5_CONFIG_ENCTYPE 0x00000200 +#define KADM5_CONFIG_ADBNAME 0x00000400 +#define KADM5_CONFIG_ADB_LOCKFILE 0x00000800 +/*#define KADM5_CONFIG_PROFILE 0x00001000*/ +#define KADM5_CONFIG_ACL_FILE 0x00002000 +#define KADM5_CONFIG_KADMIND_PORT 0x00004000 +#define KADM5_CONFIG_ENCTYPES 0x00008000 +#define KADM5_CONFIG_ADMIN_SERVER 0x00010000 +#define KADM5_CONFIG_DICT_FILE 0x00020000 +#define KADM5_CONFIG_MKEY_FROM_KBD 0x00040000 +#define KADM5_CONFIG_KPASSWD_PORT 0x00080000 +#define KADM5_CONFIG_OLD_AUTH_GSSAPI 0x00100000 +#define KADM5_CONFIG_NO_AUTH 0x00200000 +#define KADM5_CONFIG_AUTH_NOFALLBACK 0x00400000 +#ifdef notyet /* Novell */ +#define KADM5_CONFIG_KPASSWD_SERVER 0x00800000 +#endif +#define KADM5_CONFIG_IPROP_ENABLED 0x01000000 +#define KADM5_CONFIG_ULOG_SIZE 0x02000000 +#define KADM5_CONFIG_POLL_TIME 0x04000000 +#define KADM5_CONFIG_IPROP_LOGFILE 0x08000000 +#define KADM5_CONFIG_IPROP_PORT 0x10000000 +#define KADM5_CONFIG_KVNO 0x20000000 +/* + * 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 + + /* Deprecated except for db2 backwards compatibility. Don't add + new uses except as fallbacks for parameters that should be + specified in the database module section of the config + file. */ + char * dbname; + + /* dummy fields to preserve abi for now */ + char * admin_dbname_was_here; + char * admin_lockfile_was_here; + + 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; + krb5_kvno kvno; + bool_t iprop_enabled; + uint32_t iprop_ulogsize; + krb5_deltat iprop_poll_time; + char * iprop_logfile; +/* char * iprop_server;*/ + int iprop_port; +} 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; + char * realm_host_based_services; + char * realm_no_host_referral; + 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 *); + +krb5_error_code kadm5_init_iprop(void *server_handle, char **db_args); + +/* + * kadm5_get_principal_keys is used only by kadmin.local to extract existing + * keys from the database without changing them. It should never be exposed + * to the network protocol. + */ +kadm5_ret_t kadm5_get_principal_keys(void *server_handle, + krb5_principal principal, + krb5_keyblock **keyblocks, + int *n_keys); + +#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 */ + +KADM5INT_END_DECLS + +#endif /* __KADM5_ADMIN_H__ */ diff --git a/krb5-1-7/src/lib/kadm5/admin_internal.h b/krb5-1-7/src/lib/kadm5/admin_internal.h new file mode 100644 index 000000000..6a9d31b0c --- /dev/null +++ b/krb5-1-7/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 + +#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-7/src/lib/kadm5/admin_xdr.h b/krb5-1-7/src/lib/kadm5/admin_xdr.h new file mode 100644 index 000000000..05d1a7ea6 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/admin_xdr.h @@ -0,0 +1,64 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + * + */ + +#include +#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-7/src/lib/kadm5/alt_prof.c b/krb5-1-7/src/lib/kadm5/alt_prof.c new file mode 100644 index 000000000..f2db0a221 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/alt_prof.c @@ -0,0 +1,1145 @@ +/* + * lib/kadm/alt_prof.c + * + * Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ + +/* + * alt_prof.c - Implement alternate profile file handling. + */ +#include "k5-int.h" +#include +#include "adm_proto.h" +#include +#include +#include + +krb5_boolean krb5_match_config_pattern(const char *, const char*); +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; + char *profile_path; + char **filenames; + int i; + struct k5buf buf; + + kret = krb5_get_default_config_files (&filenames); + if (kret) + return kret; + if (envname == NULL || (kdc_config = getenv(envname)) == NULL) + kdc_config = fname; + krb5int_buf_init_dynamic(&buf); + if (kdc_config) + krb5int_buf_add(&buf, kdc_config); + for (i = 0; filenames[i] != NULL; i++) { + if (krb5int_buf_len(&buf) > 0) + krb5int_buf_add(&buf, ":"); + krb5int_buf_add(&buf, filenames[i]); + } + krb5_free_config_files(filenames); + profile_path = krb5int_buf_data(&buf); + if (profile_path == NULL) + return ENOMEM; + 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" }; + unsigned 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); + profile_free_list(values); + 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 */ + profile_free_list(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 lastidx; + + if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) { + for (lastidx=0; values[lastidx]; lastidx++); + lastidx--; + + /* Excise the entry we want from the null-terminated list, + and free up the rest. */ + if (uselast) { + *stringp = values[lastidx]; + values[lastidx] = NULL; + } else { + *stringp = values[0]; + values[0] = values[lastidx]; + values[lastidx] = NULL; + } + + /* Free the string storage */ + profile_free_list(values); + } + return(kret); +} + +/* + * krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is specified multiple times, + * collect all its string values from the alternate profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * stringp - Returned string value. + * + * Returns: + * error codes from profile_get_values() or ENOMEM + * Caller is responsible for deallocating stringp buffer + */ +krb5_error_code +krb5_aprof_get_string_all(acontext, hierarchy, stringp) + krb5_pointer acontext; + const char **hierarchy; + char **stringp; +{ + krb5_error_code kret=0; + char **values; + int lastidx = 0; + char *tmp = NULL ; + size_t buf_size = 0; + kret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (!kret) { + for (lastidx=0; values[lastidx]; lastidx++); + lastidx--; + + buf_size = strlen(values[0])+3; + for (lastidx=1; values[lastidx]; lastidx++){ + buf_size += strlen(values[lastidx]) + 3; + } + } + if (buf_size > 0) { + *stringp = calloc(1,buf_size); + if (*stringp == NULL){ + profile_free_list(values); + return ENOMEM; + } + tmp=*stringp; + strlcpy(tmp, values[0], buf_size); + for (lastidx=1; values[lastidx]; lastidx++){ + tmp = strcat(tmp, " "); + tmp = strcat(tmp, values[lastidx]); + } + /* Free the string storage */ + profile_free_list(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 */ + profile_free_list(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); +} + +/* + * Returns nonzero if it found something to copy; the caller may still + * need to check the output field or mask to see if the copy + * (allocation) was successful. Returns zero if nothing was found to + * copy, and thus the caller may want to apply some default heuristic. + * If the default action is just to use a fixed, compiled-in string, + * supply it as the default value here and ignore the return value. + */ +static int +get_string_param(char **param_out, char *param_in, + long *mask_out, long mask_in, long mask_bit, + krb5_pointer aprofile, + const char **hierarchy, + const char *config_name, + const char *default_value) +{ + char *svalue; + + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *param_out = strdup(param_in); + if (*param_out) + *mask_out |= mask_bit; + return 1; + } else if (aprofile && + !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { + *param_out = svalue; + *mask_out |= mask_bit; + return 1; + } else if (default_value) { + *param_out = strdup(default_value); + if (*param_out) + *mask_out |= mask_bit; + return 1; + } else { + return 0; + } +} +/* + * Similar, for (host-order) port number, if not already set in the + * output field; default_value==0 means no default. + */ +static void +get_port_param(int *param_out, int param_in, + long *mask_out, long mask_in, long mask_bit, + krb5_pointer aprofile, + const char **hierarchy, + const char *config_name, + int default_value) +{ + krb5_int32 ivalue; + + if (! (*mask_out & mask_bit)) { + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *mask_out |= mask_bit; + *param_out = param_in; + } else if (aprofile && + !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) { + *param_out = ivalue; + *mask_out |= mask_bit; + } else if (default_value) { + *param_out = default_value; + *mask_out |= mask_bit; + } + } +} +/* + * Similar, for delta_t; default is required. + */ +static void +get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in, + long *mask_out, long mask_in, long mask_bit, + krb5_pointer aprofile, + const char **hierarchy, + const char *config_name, + krb5_deltat default_value) +{ + krb5_deltat dtvalue; + + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *mask_out |= mask_bit; + *param_out = param_in; + } else if (aprofile && + !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { + *param_out = dtvalue; + *mask_out |= mask_bit; + } else { + *param_out = default_value; + *mask_out |= mask_bit; + } +} + +/* + * 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; + 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; + } + + if (params_in->mask & KADM5_CONFIG_KVNO) { + params.kvno = params_in->kvno; + params.mask |= KADM5_CONFIG_KVNO; + } + /* + * 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] = KRB5_CONF_REALMS; + hierarchy[1] = lrealm; + hierarchy[3] = (char *) NULL; + +#define GET_STRING_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_string_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + + /* Get the value for the admin server */ + GET_STRING_PARAM(admin_server, KADM5_CONFIG_ADMIN_SERVER, KRB5_CONF_ADMIN_SERVER, + NULL); + + 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 */ + GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME, + DEFAULT_KDB_FILE); + + params.admin_dbname_was_here = NULL; + params.admin_lockfile_was_here = NULL; + /* never set KADM5_CONFIG_ADBNAME, KADM5_CONFIG_ADB_LOCKFILE */ + + /* Get the value for the admin (policy) database lock file*/ + if (!GET_STRING_PARAM(admin_keytab, KADM5_CONFIG_ADMIN_KEYTAB, + KRB5_CONF_ADMIN_KEYTAB, NULL)) { + const char *s = getenv("KRB5_KTNAME"); + if (s == NULL) + s = DEFAULT_KADM5_KEYTAB; + params.admin_keytab = strdup(s); + if (params.admin_keytab) + params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; + } + + /* Get the name of the acl file */ + GET_STRING_PARAM(acl_file, KADM5_CONFIG_ACL_FILE, KRB5_CONF_ACL_FILE, + DEFAULT_KADM5_ACL_FILE); + + /* Get the name of the dict file */ + GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE, NULL); + +#define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_port_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + /* Get the value for the kadmind port */ + GET_PORT_PARAM(kadmind_port, KADM5_CONFIG_KADMIND_PORT, + KRB5_CONF_KADMIND_PORT, DEFAULT_KADM5_PORT); + + /* Get the value for the kpasswd port */ + GET_PORT_PARAM(kpasswd_port, KADM5_CONFIG_KPASSWD_PORT, + KRB5_CONF_KPASSWD_PORT, DEFAULT_KPASSWD_PORT); + + /* Get the value for the master key name */ + GET_STRING_PARAM(mkey_name, KADM5_CONFIG_MKEY_NAME, + KRB5_CONF_MASTER_KEY_NAME, NULL); + + /* Get the value for the master key type */ + hierarchy[2] = KRB5_CONF_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; + free(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 */ + GET_STRING_PARAM(stash_file, KADM5_CONFIG_STASH_FILE, + KRB5_CONF_KEY_STASH_FILE, NULL); + + /* Get the value for maximum ticket lifetime. */ +#define GET_DELTAT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_deltat_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + + GET_DELTAT_PARAM(max_life, KADM5_CONFIG_MAX_LIFE, KRB5_CONF_MAX_LIFE, + 24 * 60 * 60); /* 1 day */ + + /* Get the value for maximum renewable ticket lifetime. */ + GET_DELTAT_PARAM(max_rlife, KADM5_CONFIG_MAX_RLIFE, KRB5_CONF_MAX_RENEWABLE_LIFE, + 0); + + /* Get the value for the default principal expiration */ + hierarchy[2] = KRB5_CONF_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; + free(svalue); + } + } else { + params.mask |= KADM5_CONFIG_EXPIRATION; + params.expiration = 0; + } + + /* Get the value for the default principal flags */ + hierarchy[2] = KRB5_CONF_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; + free(svalue); + } else { + params.mask |= KADM5_CONFIG_FLAGS; + params.flags = KRB5_KDB_DEF_FLAGS; + } + + /* Get the value for the supported enctype/salttype matrix */ + hierarchy[2] = KRB5_CONF_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(KRB5_DEFAULT_SUPPORTED_ENCTYPES); + + 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; + + free(svalue); + } + + hierarchy[2] = KRB5_CONF_IPROP_ENABLE; + + params.iprop_enabled = FALSE; + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + + if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) { + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + params.iprop_enabled = params_in->iprop_enabled; + } else { + krb5_boolean bvalue; + if (aprofile && + !krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) { + params.iprop_enabled = bvalue; + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + } + } + + if (!GET_STRING_PARAM(iprop_logfile, KADM5_CONFIG_IPROP_LOGFILE, + KRB5_CONF_IPROP_LOGFILE, NULL)) { + if (params.mask & KADM5_CONFIG_DBNAME) { + if (asprintf(¶ms.iprop_logfile, "%s.ulog", params.dbname) >= 0) { + params.mask |= KADM5_CONFIG_IPROP_LOGFILE; + } + } + } + + GET_PORT_PARAM(iprop_port, KADM5_CONFIG_IPROP_PORT, + KRB5_CONF_IPROP_PORT, 0); + + hierarchy[2] = KRB5_CONF_IPROP_MASTER_ULOGSIZE; + + params.iprop_ulogsize = DEF_ULOGENTRIES; + params.mask |= KADM5_CONFIG_ULOG_SIZE; + + if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) { + params.mask |= KADM5_CONFIG_ULOG_SIZE; + params.iprop_ulogsize = params_in->iprop_ulogsize; + } else { + if (aprofile && !krb5_aprof_get_int32(aprofile, hierarchy, + TRUE, &ivalue)) { + if (ivalue > MAX_ULOGENTRIES) + params.iprop_ulogsize = MAX_ULOGENTRIES; + else if (ivalue <= 0) + params.iprop_ulogsize = DEF_ULOGENTRIES; + else + params.iprop_ulogsize = ivalue; + params.mask |= KADM5_CONFIG_ULOG_SIZE; + } + } + + GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME, + KRB5_CONF_IPROP_SLAVE_POLL, 2 * 60); /* 2m */ + + *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) { + free(params->dbname); + free(params->mkey_name); + free(params->stash_file); + free(params->keysalts); + free(params->admin_server); + free(params->admin_keytab); + free(params->dict_file); + free(params->acl_file); + free(params->realm); + free(params->iprop_logfile); + } + 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; + } + snprintf(admin_name, maxlen, "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 KDC code 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; + char *no_refrls = 0; + char *host_based_srvcs = 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] = KRB5_CONF_REALMS; + hierarchy[1] = lrealm; + hierarchy[2] = KRB5_CONF_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] = KRB5_CONF_KDC_PORTS; + if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) + rparams->realm_kdc_ports = svalue; + hierarchy[2] = KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_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; + free(svalue); + } + + /* Get the value for the stashfile */ + hierarchy[2] = KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_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; + free(svalue); + } + + hierarchy[2] = KRB5_CONF_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; + } + + hierarchy[2] = KRB5_CONF_NO_HOST_REFERRAL; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls)) + rparams->realm_no_host_referral = no_refrls; + else + no_refrls = 0; + + if (!no_refrls || krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) { + hierarchy[2] = KRB5_CONF_HOST_BASED_SERVICES; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &host_based_srvcs)) + rparams->realm_host_based_services = host_based_srvcs; + else + host_based_srvcs = 0; + } + + /* Get the value for the default principal flags */ + hierarchy[2] = KRB5_CONF_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; + free(svalue); + } + + rparams->realm_keysalts = NULL; + rparams->realm_num_keysalts = 0; + +cleanup: + if (aprofile) + krb5_aprof_finish(aprofile); + 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) { + free(rparams->realm_profile); + free(rparams->realm_dbname); + free(rparams->realm_mkey_name); + free(rparams->realm_stash_file); + free(rparams->realm_keysalts); + free(rparams->realm_kdc_ports); + free(rparams->realm_kdc_tcp_ports); + free(rparams->realm_acl_file); + free(rparams->realm_no_host_referral); + free(rparams->realm_host_based_services); + free(rparams); + } + return(0); +} +/* + * match_config_pattern - + * returns TRUE is the pattern is found in the attr's list of values. + * Otherwise - FALSE. + * In conf file the values are separates by commas or whitespaces. + */ +krb5_boolean +krb5_match_config_pattern(const char *string, const char *pattern) +{ + const char *ptr; + char next = '\0'; + int len = strlen(pattern); + + for (ptr = strstr(string,pattern); ptr != 0; ptr = strstr(ptr+len,pattern)) { + if (ptr == string || isspace(*(ptr-1)) || *(ptr-1) ==',') { + next = *(ptr + len); + if (next == '\0' || isspace(next) || next ==',') { + return TRUE; + } + } + } + return FALSE; +} + + + diff --git a/krb5-1-7/src/lib/kadm5/chpass_util.c b/krb5-1-7/src/lib/kadm5/chpass_util.c new file mode 100644 index 000000000..e1fbb5849 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/chpass_util.c @@ -0,0 +1,258 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + */ + + +#include +#include "autoconf.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include + +#include +#include "admin_internal.h" + +#include + +#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. + * + * 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 */ + snprintf(buffer, sizeof(buffer), "%s %s", error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE)); + snprintf(msg_ret, msg_len, "%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) { + snprintf(msg_ret, msg_len, "%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) { + snprintf(msg_ret, msg_len, 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) { + snprintf(msg_ret, msg_len, 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'; + + snprintf(msg_ret, msg_len, 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 ... */ + snprintf(buffer, sizeof(buffer), "%s %s", error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE)); + snprintf(msg_ret, msg_len, "%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-7/src/lib/kadm5/chpass_util_strings.et b/krb5-1-7/src/lib/kadm5/chpass_util_strings.et new file mode 100644 index 000000000..c65010ae1 --- /dev/null +++ b/krb5-1-7/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." +# /* */ + +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." +# /* */ + + +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." +# /* */ + +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-7/src/lib/kadm5/clnt/Makefile.in b/krb5-1-7/src/lib/kadm5/clnt/Makefile.in new file mode 100644 index 000000000..acc7cfef9 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/Makefile.in @@ -0,0 +1,77 @@ +thisconfigdir=../../.. +myfulldir=lib/kadm5/clnt +mydir=lib/kadm5/clnt +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5 +DEFS= + +LIBBASE=kadm5clnt +LIBMAJOR=6 +LIBMINOR=0 +STOBJLISTS=../OBJS.ST OBJS.ST +SHLIB_EXPDEPS=\ + $(TOPLIBD)/libgssrpc$(SHLIBEXT) \ + $(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_LIBDEP) +SHLIB_EXPLIBS=-lgssrpc -lgssapi_krb5 -lkrb5 -lk5crypto $(SUPPORT_LIB) -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 darwin.exports + +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@ + diff --git a/krb5-1-7/src/lib/kadm5/clnt/client_handle.c b/krb5-1-7/src/lib/kadm5/clnt/client_handle.c new file mode 100644 index 000000000..895777a6e --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/client_handle.c @@ -0,0 +1,9 @@ +#include +#include +#include "client_internal.h" + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} diff --git a/krb5-1-7/src/lib/kadm5/clnt/client_init.c b/krb5-1-7/src/lib/kadm5/clnt/client_init.c new file mode 100644 index 000000000..82bec3c4e --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/client_init.c @@ -0,0 +1,849 @@ +/* + * 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 +#include +#include "autoconf.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include +#include +#include +#include +#include /* for KRB5_ADM_DEFAULT_PORT */ +#include +#ifdef __STDC__ +#include +#endif + +#include +#include +#include "client_internal.h" +#include +#include "iprop.h" + +#include +#include +#include +#include + +#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 *iprop_svc; + int iprop_enable = 0; + 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; + } + memset(handle, 0, sizeof(*handle)); + 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->context = 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; + } + +#if 0 /* Since KDC config params can now be put in krb5.conf, these + could show up even when you're just using the remote kadmin + client. */ +#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; + } +#endif + + 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; + } + + /* + * If the service_name and client_name are iprop-centric, + * we need to clnttcp_create to the appropriate RPC prog. + */ + iprop_svc = strdup(KIPROP_SVC_NAME); + if (iprop_svc == NULL) + return ENOMEM; + + if (service_name != NULL && + (strstr(service_name, iprop_svc) != NULL) && + (strstr(client_name, iprop_svc) != NULL)) + iprop_enable = 1; + else + iprop_enable = 0; + + 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)); + if (iprop_enable) + addr.sin_port = htons((u_short) handle->params.iprop_port); + else + addr.sin_port = htons((u_short) handle->params.kadmind_port); + + fd = RPC_ANYSOCK; + + if (iprop_enable) { + handle->clnt = clnttcp_create(&addr, KRB5_IPROP_PROG, KRB5_IPROP_VERS, + &fd, 0, 0); + } else + 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; + + /* + * Bypass the remainder of the code and return straightaway + * if the gss service requested is kiprop + */ + if (iprop_enable == 1) { + code = 0; + *server_handle = (void *) handle; + goto cleanup; + } + + 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; + if (asprintf(&handle->cache_name, "%s:%s", + krb5_cc_get_type(handle->context, ccache), + krb5_cc_get_name(handle->context, ccache)) < 0) { + handle->cache_name = NULL; + code = ENOMEM; + goto error; + } + } else { + static int counter = 0; + + if (asprintf(&handle->cache_name, "MEMORY:kadm5_%u", counter++) < 0) { + handle->cache_name = NULL; + code = ENOMEM; + goto error; + } + 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; + int n; + + 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) { + n = snprintf(full_svcname, full_svcname_len, "%s@%s", + svcname, realm); + if (n < 0 || n >= full_svcname_len) + goto error; + } else { + /* krb5_princ_realm(client) is not null terminated */ + n = snprintf(full_svcname, full_svcname_len, "%s@%.*s", + svcname, krb5_princ_realm(ctx, client)->length, + krb5_princ_realm(ctx, client)->data); + if (n < 0 || n >= full_svcname_len) + goto error; + } + + /* Credentials for kadmin don't need to be forwardable or proxiable. */ + if (init_type != INIT_CREDS) { + krb5_get_init_creds_opt_init(&opt); + krb5_get_init_creds_opt_set_forwardable(&opt, 0); + krb5_get_init_creds_opt_set_proxiable(&opt, 0); + } + + 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; + gss_client = gss_target = GSS_C_NO_NAME; + + /* 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; +#if 0 /* for debugging only */ + { + OM_uint32 maj_status, min_status, message_context = 0; + gss_buffer_desc status_string; + do { + maj_status = gss_display_status(&min_status, + gssstat, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &message_context, + &status_string); + if (maj_status == GSS_S_COMPLETE) { + fprintf(stderr, "MAJ: %.*s\n", + (int) status_string.length, + (char *)status_string.value); + gss_release_buffer(&min_status, &status_string); + } else { + fprintf(stderr, + "MAJ? gss_display_status returns 0x%lx?!\n", + (unsigned long) maj_status); + message_context = 0; + } + } while (message_context != 0); + do { + maj_status = gss_display_status(&min_status, + minor_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &message_context, + &status_string); + if (maj_status == GSS_S_COMPLETE) { + fprintf(stderr, "MIN: %.*s\n", + (int) status_string.length, + (char *)status_string.value); + gss_release_buffer(&min_status, &status_string); + } else { + fprintf(stderr, + "MIN? gss_display_status returns 0x%lx?!\n", + (unsigned long) maj_status); + message_context = 0; + } + } while (message_context != 0); + } +#endif + 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); +} + +/* + * Stub function for kadmin. It was created to eliminate the dependency on + * libkdb's ulog functions. The srv equivalent makes the actual calls. + */ +krb5_error_code +kadm5_init_iprop(void *handle, char **db_args) +{ + return (0); +} diff --git a/krb5-1-7/src/lib/kadm5/clnt/client_internal.h b/krb5-1-7/src/lib/kadm5/clnt/client_internal.h new file mode 100644 index 000000000..c5ebfec77 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/clnt/client_principal.c b/krb5-1-7/src/lib/kadm5/clnt/client_principal.c new file mode 100644 index 000000000..51135f436 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/client_principal.c @@ -0,0 +1,547 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include +#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-7/src/lib/kadm5/clnt/client_rpc.c b/krb5-1-7/src/lib/kadm5/clnt/client_rpc.c new file mode 100644 index 000000000..28d9b6b7c --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/client_rpc.c @@ -0,0 +1,327 @@ +#include +#include +#include +#include +#include /* for memset prototype */ + +#ifdef HAVE_MEMORY_H +#include +#endif + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 120, 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-7/src/lib/kadm5/clnt/clnt_chpass_util.c b/krb5-1-7/src/lib/kadm5/clnt/clnt_chpass_util.c new file mode 100644 index 000000000..71ab64937 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/clnt_chpass_util.c @@ -0,0 +1,16 @@ +#include +#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-7/src/lib/kadm5/clnt/clnt_policy.c b/krb5-1-7/src/lib/kadm5/clnt/clnt_policy.c new file mode 100644 index 000000000..6877ec388 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include "client_internal.h" +#include +#include +#include + +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-7/src/lib/kadm5/clnt/clnt_privs.c b/krb5-1-7/src/lib/kadm5/clnt/clnt_privs.c new file mode 100644 index 000000000..5f7ed4370 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#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-7/src/lib/kadm5/clnt/deps b/krb5-1-7/src/lib/kadm5/clnt/deps new file mode 100644 index 000000000..1bcee5666 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/deps @@ -0,0 +1,82 @@ +# +# Generated makefile dependencies follow. +# +clnt_policy.so clnt_policy.po $(OUTPRE)clnt_policy.$(OBJEXT): \ + $(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/kdb.h $(SRCTOP)/include/krb5.h client_internal.h \ + clnt_policy.c +client_rpc.so client_rpc.po $(OUTPRE)client_rpc.$(OBJEXT): \ + $(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/kdb.h \ + $(SRCTOP)/include/krb5.h client_rpc.c +client_principal.so client_principal.po $(OUTPRE)client_principal.$(OBJEXT): \ + $(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/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_ext.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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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/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/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/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/kdb.h \ + $(SRCTOP)/include/krb5.h client_internal.h clnt_chpass_util.c diff --git a/krb5-1-7/src/lib/kadm5/clnt/libkadm5clnt.exports b/krb5-1-7/src/lib/kadm5/clnt/libkadm5clnt.exports new file mode 100644 index 000000000..7f11f320a --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/clnt/libkadm5clnt.exports @@ -0,0 +1,132 @@ +_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 +kadm5_init_iprop diff --git a/krb5-1-7/src/lib/kadm5/deps b/krb5-1-7/src/lib/kadm5/deps new file mode 100644 index 000000000..09b77a8d5 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/deps @@ -0,0 +1,101 @@ +# +# Generated makefile dependencies follow. +# +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/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/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/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/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/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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h logger.c diff --git a/krb5-1-7/src/lib/kadm5/kadm_err.et b/krb5-1-7/src/lib/kadm5/kadm_err.et new file mode 100644 index 000000000..da18a74eb --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/kadm_rpc.h b/krb5-1-7/src/lib/kadm5/kadm_rpc.h new file mode 100644 index 000000000..d793ed88c --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/kadm_rpc.h @@ -0,0 +1,305 @@ +#ifndef __KADM_RPC_H__ +#define __KADM_RPC_H__ + +#include + +#include +#include + +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-7/src/lib/kadm5/kadm_rpc_xdr.c b/krb5-1-7/src/lib/kadm5/kadm_rpc_xdr.c new file mode 100644 index 000000000..00b9ae226 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/kadm_rpc_xdr.c @@ -0,0 +1,1067 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + + + +static bool_t xdr_krb5_boolean(XDR *xdrs, krb5_boolean *kbool) +{ + bool_t val; + + switch (xdrs->x_op) { + case XDR_DECODE: + if (!xdr_bool(xdrs, &val)) + return FALSE; + + *kbool = (val == FALSE) ? FALSE : TRUE; + return TRUE; + + case XDR_ENCODE: + val = *kbool ? TRUE : FALSE; + return xdr_bool(xdrs, &val); + + case XDR_FREE: + return TRUE; + } + + return FALSE; +} + +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_krb5_boolean(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_krb5_boolean(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_krb5_boolean(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-7/src/lib/kadm5/logger.c b/krb5-1-7/src/lib/kadm5/logger.c new file mode 100644 index 000000000..ef3735a37 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/logger.c @@ -0,0 +1,971 @@ +/* + * lib/kadm/logger.c + * + * Copyright 1995, 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. + * + */ + +/* 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 +#include +#ifdef HAVE_SYSLOG_H +#include +#endif /* HAVE_SYSLOG_H */ +#include + +#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 + * SYSLOG[=[:]] + * STDERR + * CONSOLE + * DEVICE= + * + * Where: + * is ":" for open/append, "=" for open/create. + * is a valid path name. + * is one of: (default = ERR) + * EMERG + * ALERT + * CRIT + * ERR + * WARNING + * NOTICE + * INFO + * DEBUG + * is one of: (default = AUTH) + * KERN + * USER + * MAIL + * DAEMON + * AUTH + * LPR + * NEWS + * UUCP + * CRON + * LOCAL0..LOCAL7 + * 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) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +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; + + if (whoami == NULL || format == NULL) + return; + + /* Make the header */ + snprintf(outbuf, sizeof(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 */ + vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap); + + /* + * 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]-> 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 + * 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) { + set_cloexec_file(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 */ + }; + unsigned 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) { + set_cloexec_file(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) { + set_cloexec_file(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; ilog_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 = strdup(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) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; + +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) + * [](): + * + * (short form) + * + */ + 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 + snprintf(cp, sizeof(outbuf) - (cp-outbuf), " %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 + snprintf(cp, sizeof(outbuf) - (cp-outbuf), " "); +#endif + syslogp = &outbuf[strlen(outbuf)]; + + /* Now format the actual message */ + vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist); + + /* + * 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) { + set_cloexec_file(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-7/src/lib/kadm5/misc_free.c b/krb5-1-7/src/lib/kadm5/misc_free.c new file mode 100644 index 000000000..9dc91b53f --- /dev/null +++ b/krb5-1-7/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 +#include +#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-7/src/lib/kadm5/ovsec_glue.c b/krb5-1-7/src/lib/kadm5/ovsec_glue.c new file mode 100644 index 000000000..a3ae6de42 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/ovsec_glue.c @@ -0,0 +1,194 @@ +#define USE_KADM5_API_VERSION 1 +#include +#include + +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-7/src/lib/kadm5/server_internal.h b/krb5-1-7/src/lib/kadm5/server_internal.h new file mode 100644 index 000000000..4e890e8aa --- /dev/null +++ b/krb5-1-7/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 +#endif +#include +#include +#include +#include +#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-7/src/lib/kadm5/srv/Makefile.in b/krb5-1-7/src/lib/kadm5/srv/Makefile.in new file mode 100644 index 000000000..fcb92d797 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/Makefile.in @@ -0,0 +1,94 @@ +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=6 +LIBMINOR=0 +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) $(SUPPORT_LIBDEP) +SHLIB_EXPLIBS = -lgssrpc -lgssapi_krb5 -lkdb5 $(KDB5_DB_LIB) \ + -lkrb5 -lk5crypto $(SUPPORT_LIB) -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 darwin.exports + +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@ + diff --git a/krb5-1-7/src/lib/kadm5/srv/adb_xdr.c b/krb5-1-7/src/lib/kadm5/srv/adb_xdr.c new file mode 100644 index 000000000..d5d17062a --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include "server_internal.h" +#include "admin_xdr.h" +#ifdef HAVE_MEMORY_H +#include +#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-7/src/lib/kadm5/srv/deps b/krb5-1-7/src/lib/kadm5/srv/deps new file mode 100644 index 000000000..f4da1d2c5 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/deps @@ -0,0 +1,159 @@ +# +# Generated makefile dependencies follow. +# +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/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/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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/gssapi/gssapi_ext.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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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_ext.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 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/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/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/kdb.h $(SRCTOP)/include/krb5.h adb_xdr.c diff --git a/krb5-1-7/src/lib/kadm5/srv/libkadm5srv.exports b/krb5-1-7/src/lib/kadm5/srv/libkadm5srv.exports new file mode 100644 index 000000000..545d43b70 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/libkadm5srv.exports @@ -0,0 +1,168 @@ +_kadm5_check_handle +_kadm5_chpass_principal_util +kadm5int_acl_check +kadm5int_acl_check_krb +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_principal_keys +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_get_string_all +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 +krb5_match_config_pattern +master_db +master_keyblock +master_keylist +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 +kadm5_init_iprop diff --git a/krb5-1-7/src/lib/kadm5/srv/server_acl.c b/krb5-1-7/src/lib/kadm5/srv/server_acl.c new file mode 100644 index 000000000..af42fba89 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_acl.c @@ -0,0 +1,833 @@ +/* + * lib/kadm5/srv/server_acl.c + * + * Copyright 1995-2004, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include +#include +#include +#include "k5-int.h" +#include +#include +#include "adm_proto.h" +#include "server_acl.h" +#include + +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 }, + { 'p', ACL_IPROP }, + { '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++ ) { + int byte; + byte = fgetc(fp); + acl_buf[i] = byte; + if (byte == (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 ::= [] + * [ [ + * []]] + */ + 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 = strdup(acle_principal); + if (acle->ae_name) { + 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 (acle) { + 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 = NULL, *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) { + set_cloexec_file(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; ilength; 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; ilength; 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_krb() - Is this operation permitted for this principal? + */ +krb5_boolean +kadm5int_acl_check_krb(kcontext, caller_princ, opmask, principal, restrictions) + krb5_context kcontext; + krb5_const_principal caller_princ; + krb5_int32 opmask; + krb5_const_principal principal; + restriction_t **restrictions; +{ + krb5_boolean retval; + aent_t *aentry; + + DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n")); + + retval = FALSE; + + aentry = kadm5int_acl_find_entry(kcontext, caller_princ, principal); + if (aentry) { + if ((aentry->ae_op_allowed & opmask) == opmask) { + retval = TRUE; + if (restrictions) { + *restrictions = + (aentry->ae_restrictions && aentry->ae_restrictions->mask) + ? aentry->ae_restrictions + : (restriction_t *) NULL; + } + } + } + + DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n", + retval)); + return retval; +} + +/* + * 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; + gss_buffer_desc caller_buf; + gss_OID caller_oid; + OM_uint32 emaj, emin; + krb5_error_code code; + krb5_principal caller_princ; + + if (GSS_ERROR(emaj = gss_display_name(&emin, caller, &caller_buf, + &caller_oid))) + return FALSE; + + code = krb5_parse_name(kcontext, (char *) caller_buf.value, + &caller_princ); + + gss_release_buffer(&emin, &caller_buf); + + if (code != 0) + return FALSE; + + retval = kadm5int_acl_check_krb(kcontext, caller_princ, + opmask, principal, restrictions); + + krb5_free_principal(kcontext, caller_princ); + + 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-7/src/lib/kadm5/srv/server_acl.h b/krb5-1-7/src/lib/kadm5/srv/server_acl.h new file mode 100644 index 000000000..c4c478993 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_acl.h @@ -0,0 +1,109 @@ +/* + * lib/kadm5/srv/server_acl.h + * + * Copyright 1995-2004, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 */ + +/* + * 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_IPROP 512 +#define ACL_RENAME (ACL_ADD+ACL_DELETE) + +#define ACL_ALL_MASK (ACL_ADD | \ + ACL_DELETE | \ + ACL_MODIFY | \ + ACL_CHANGEPW | \ + ACL_INQUIRE | \ + ACL_LIST | \ + ACL_IPROP | \ + 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_boolean kadm5int_acl_check_krb + (krb5_context, + krb5_const_principal, + krb5_int32, + krb5_const_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-7/src/lib/kadm5/srv/server_dict.c b/krb5-1-7/src/lib/kadm5/srv/server_dict.c new file mode 100644 index 000000000..8129994f3 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_dict.c @@ -0,0 +1,207 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_MEMORY_H +#include +#endif +#include "adm_proto.h" +#include +#include "server_internal.h" +#include "k5-platform.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 + * 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 + * 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; + } + set_cloexec_fd(fd); + if (fstat(fd, &sb) == -1) { + close(fd); + return errno; + } + if ((word_block = (char *) malloc(sb.st_size + 1)) == NULL) + return ENOMEM; + 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 ENOMEM; + 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. + * 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 + * 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-7/src/lib/kadm5/srv/server_handle.c b/krb5-1-7/src/lib/kadm5/srv/server_handle.c new file mode 100644 index 000000000..53abe94dd --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_handle.c @@ -0,0 +1,9 @@ +#include +#include +#include "server_internal.h" + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} diff --git a/krb5-1-7/src/lib/kadm5/srv/server_init.c b/krb5-1-7/src/lib/kadm5/srv/server_init.c new file mode 100644 index 000000000..febf79bdf --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_init.c @@ -0,0 +1,470 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include +#include +#include "k5-int.h" /* needed for gssapiP_krb5.h */ +#include +#include +#include +#include "server_internal.h" +#include "osconf.h" +#include "iprop_hdr.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_ENCTYPE | \ + KADM5_CONFIG_FLAGS | \ + KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \ + KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES) + +#define IPROP_REQUIRED_PARAMS \ + (KADM5_CONFIG_IPROP_ENABLED | \ + KADM5_CONFIG_IPROP_LOGFILE | \ + KADM5_CONFIG_IPROP_PORT) + + if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { + krb5_free_context(handle->context); + free_db_args(handle); + free(handle); + return KADM5_MISSING_CONF_PARAMS; + } + if ((handle->params.mask & KADM5_CONFIG_IPROP_ENABLED) == KADM5_CONFIG_IPROP_ENABLED + && handle->params.iprop_enabled) { + if ((handle->params.mask & IPROP_REQUIRED_PARAMS) != IPROP_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); +} + +krb5_error_code +kadm5_init_iprop(void *handle, char **db_args) +{ + kadm5_server_handle_t iprop_h; + krb5_error_code retval; + + iprop_h = handle; + if (iprop_h->params.iprop_enabled) { + ulog_set_role(iprop_h->context, IPROP_MASTER); + if ((retval = ulog_map(iprop_h->context, + iprop_h->params.iprop_logfile, + iprop_h->params.iprop_ulogsize, + FKCOMMAND, db_args)) != 0) + return (retval); + } + return (0); +} diff --git a/krb5-1-7/src/lib/kadm5/srv/server_kdb.c b/krb5-1-7/src/lib/kadm5/srv/server_kdb.c new file mode 100644 index 000000000..47f00c071 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/server_kdb.c @@ -0,0 +1,447 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include "k5-int.h" +#include +#include "server_internal.h" + +krb5_principal master_princ; +krb5_keyblock master_keyblock; /* local mkey */ +krb5_keylist_node *master_keylist = NULL; +krb5_actkvno_node *active_mkey_list = NULL; +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; + krb5_kvno mkvno = IGNORE_VNO; + + 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; + + /* + * Fetch the local mkey, may not be the latest but that's okay because we + * really want the list of all mkeys and those can be retrieved with any + * valid mkey. + */ + ret = krb5_db_fetch_mkey(handle->context, master_princ, + master_keyblock.enctype, from_kbd, + FALSE /* only prompt once */, + handle->params.stash_file, + &mkvno /* get the kvno of the returned mkey */, + NULL /* I'm not sure about this, + but it's what the kdc does --marc */, + &master_keyblock); + if (ret) + goto done; + +#if 0 /************** Begin IFDEF'ed OUT *******************************/ + /* + * krb5_db_fetch_mkey_list will verify mkey so don't call + * krb5_db_verify_master_key() + */ + if ((ret = krb5_db_verify_master_key(handle->context, master_princ, + IGNORE_VNO, &master_keyblock))) { + krb5_db_fini(handle->context); + return ret; + } +#endif /**************** END IFDEF'ed OUT *******************************/ + + if ((ret = krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock, mkvno, &master_keylist))) { + krb5_db_fini(handle->context); + return (ret); + } + + if ((ret = krb5_dbe_fetch_act_key_list(handle->context, master_princ, + &active_mkey_list))) { + 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]; + krb5_keyblock *tmp_mkey; + + if (r == NULL) { + if ((ret = krb5_get_default_realm(handle->context, &realm))) + return ret; + } else { + realm = r; + } + + if (asprintf(&hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm) < 0) { + hist_name = NULL; + goto done; + } + + 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_dbe_find_mkey(handle->context, master_keylist, &hist_db, + &tmp_mkey); + if (ret) + goto done; + + ret = krb5_dbekd_decrypt_key_data(handle->context, tmp_mkey, + 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-7/src/lib/kadm5/srv/server_misc.c b/krb5-1-7/src/lib/kadm5/srv/server_misc.c new file mode 100644 index 000000000..cd65371c9 --- /dev/null +++ b/krb5-1-7/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 +#include +#include + +/* for strcasecmp */ +#include + +#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-7/src/lib/kadm5/srv/svr_chpass_util.c b/krb5-1-7/src/lib/kadm5/srv/svr_chpass_util.c new file mode 100644 index 000000000..c8b63100a --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/svr_chpass_util.c @@ -0,0 +1,16 @@ +#include +#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-7/src/lib/kadm5/srv/svr_iters.c b/krb5-1-7/src/lib/kadm5/srv/svr_iters.c new file mode 100644 index 000000000..757d3ab0e --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/svr_iters.c @@ -0,0 +1,274 @@ +/* + * 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 +#include +#include +#ifdef SOLARIS_REGEXPS +#include +#endif +#ifdef POSIX_REGEXPS +#include +#endif +#include + +#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 +}; + +/* XXX Duplicated in kdb5_util! */ +/* + * 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 ? 3 : 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++ = '$'; + *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; + + *princs = NULL; + *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-7/src/lib/kadm5/srv/svr_misc_free.c b/krb5-1-7/src/lib/kadm5/srv/svr_misc_free.c new file mode 100644 index 000000000..d20339705 --- /dev/null +++ b/krb5-1-7/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 +#include +#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-7/src/lib/kadm5/srv/svr_policy.c b/krb5-1-7/src/lib/kadm5/srv/svr_policy.c new file mode 100644 index 000000000..7add6714a --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/svr_policy.c @@ -0,0 +1,314 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include "server_internal.h" +#include +#include +#include + +#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. + * 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. + * 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) + 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) { + 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 = strdup(t->name)) == NULL) { + krb5_db_free_policy(handle->context, t); + return ENOMEM; + } + 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-7/src/lib/kadm5/srv/svr_principal.c b/krb5-1-7/src/lib/kadm5/srv/svr_principal.c new file mode 100644 index 000000000..f0fe849bb --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/srv/svr_principal.c @@ -0,0 +1,2315 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "server_internal.h" +#include +#include +#ifdef USE_PASSWORD_SERVER +#include +#include + +#endif + +#ifdef USE_VALGRIND +#include +#else +#define VALGRIND_CHECK_DEFINED(LVALUE) ((void)0) +#endif + +extern krb5_principal master_princ; +extern krb5_principal hist_princ; +extern krb5_keyblock master_keyblock; +extern krb5_keylist_node *master_keylist; +extern krb5_actkvno_node *active_mkey_list; +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, krb5_keyblock *mkey, + 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; + + VALGRIND_CHECK_DEFINED(*inprinc); + 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); + krb5_princ_component(context, tempprinc, i)->magic = KV5M_DATA; + } + + 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); +} + +/* + * Set *passptr to NULL if the request looks like the first part of a krb5 1.6 + * addprinc -randkey operation. The krb5 1.6 dummy password for these requests + * was invalid UTF-8, which runs afoul of the arcfour string-to-key. + */ +static void +check_1_6_dummy(kadm5_principal_ent_t entry, long mask, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, char **passptr) +{ + int i; + char *password = *passptr; + + /* Old-style randkey operations disallowed tickets to start. */ + if (!(mask & KADM5_ATTRIBUTES) || + !(entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)) + return; + + /* The 1.6 dummy password was the octets 1..255. */ + for (i = 0; (unsigned char) password[i] == i + 1; i++); + if (password[i] != '\0' || i != 255) + return; + + /* This will make the caller use a random password instead. */ + *passptr = NULL; +} + +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; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + check_1_6_dummy(entry, mask, n_ks_tuple, ks_tuple, &password); + + /* + * 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 == 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 (password) { + ret = passwd_check(handle, password, (mask & KADM5_POLICY), + &polent, entry->principal); + if (ret) { + 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 */ + + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, &act_kvno, &act_mkey); + if (ret) { + krb5_db_free_principal(handle->context, &kdb, 1); + if (mask & KADM5_POLICY) + (void) kadm5_free_policy_ent(handle->lhandle, &polent); + return (ret); + } + + if (password) { + ret = krb5_dbe_cpw(handle->context, act_mkey, + 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); + } else { + /* Null password means create with random key (new in 1.8). */ + 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, + FALSE, &kdb); + } + if (ret) { + krb5_db_free_principal(handle->context, &kdb, 1); + if (mask & KADM5_POLICY) + (void) kadm5_free_policy_ent(handle->lhandle, &polent); + return(ret); + } + + /* Record the master key VNO used to encrypt this entry's keys */ + ret = krb5_dbe_update_mkvno(handle->context, &kdb, act_kvno); + if (ret) + { + 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; icontext, 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 = strdup(adb.policy)) == NULL) { + ret = ENOMEM; + goto done; + } + } + + if (mask & KADM5_AUX_ATTRIBUTES) + entry->aux_attributes = adb.aux_attributes; + + if ((mask & KADM5_PRINCIPAL) && + (ret = krb5_copy_principal(handle->context, kdb.princ, + &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 entry->kvno) + entry->kvno = kdb.key_data[i].key_data_kvno; + + ret = krb5_dbe_lookup_mkvno(handle->context, &kdb, &entry->mkvno); + if (ret) + goto done; + + /* + * It's my understanding that KADM5_API_VERSION_1 is for OpenVision admin + * system compatiblity and is not required to maintain at this point so I'm + * commenting out this code. + * -- Will Fiveash + */ +#if 0 /************** Begin IFDEF'ed OUT *******************************/ + 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; + } +#endif /**************** END IFDEF'ed OUT *******************************/ + + /* + * 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 *mkey, + 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, + mkey, + &(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, krb5_keyblock *mkey, 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, + mkey, + &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; + +#ifdef USE_PASSWORD_SERVER +static krb5_boolean +kadm5_use_password_server (void) +{ + return use_password_server; +} +#endif + +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 *buffer) +{ + kadm5_ret_t ret; + int data_pipe[2]; + + ret = pipe (data_pipe); + if (ret) + ret = errno; + + if (!ret) { + pid_t pid = fork (); + if (pid == -1) { + ret = errno; + close (data_pipe[0]); + close (data_pipe[1]); + } else if (pid == 0) { + /* The child: */ + + if (dup2 (data_pipe[0], STDIN_FILENO) == -1) + _exit (1); + + close (data_pipe[0]); + close (data_pipe[1]); + + execv (task_path, task_argv); + + _exit (1); /* Fail if execv fails */ + } else { + /* The parent: */ + int status; + + ret = 0; + + close (data_pipe[0]); + + /* Write out the buffer to the child, add \n */ + if (buffer) { + if (krb5_net_write (context, data_pipe[1], buffer, strlen (buffer)) < 0 + || krb5_net_write (context, data_pipe[1], "\n", 1) < 0) + { + /* kill the child to make sure waitpid() won't hang later */ + ret = errno; + kill (pid, SIGKILL); + } + } + close (data_pipe[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; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; + + 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_find_act_mkey(handle->context, master_keylist, + active_mkey_list, &act_kvno, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_cpw(handle->context, act_mkey, + 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; + + ret = krb5_dbe_update_mkvno(handle->context, &kdb, act_kvno); + 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, + act_mkey, + kdb_save.n_key_data, + kdb_save.key_data, &hist); + if (ret) + goto done; + + ret = check_pw_reuse(handle->context, act_mkey, &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, act_mkey, &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; + + if (!ret) { + pstring = malloc ((princ->length + 1) * sizeof (char)); + if (pstring == NULL) { ret = ENOMEM; } + } + + if (!ret) { + memcpy (pstring, princ->data, princ->length); + pstring [princ->length] = '\0'; + argv[2] = pstring; + + ret = kadm5_launch_task (handle->context, path, argv, password); + } + + 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; + krb5_keyblock *act_mkey; + + 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_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_crk(handle->context, act_mkey, + 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, act_mkey, &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, act_mkey, 1, key_data, + keyblocks, NULL); + if (ret) + goto done; + } else { + ret = decrypt_key_data(handle->context, act_mkey, + 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; + krb5_keyblock *act_mkey; + + 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 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; + + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + + /* use tmp_key_data as temporary location and reallocate later */ + ret = krb5_dbekd_encrypt_key_data(handle->context, act_mkey, + 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; + krb5_keyblock *act_mkey; + + 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 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_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbekd_encrypt_key_data(handle->context, + act_mkey, + &keyblocks[i], + n_ks_tuple ? &keysalt : NULL, + kvno + 1, + &tmp_key_data); + if (ret) + goto done; + + tptr = &kdb.key_data[i]; + 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(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; +} + +/* + * Return the list of keys like kadm5_randkey_principal, + * but don't modify the principal. + */ +kadm5_ret_t +kadm5_get_principal_keys(void *server_handle /* IN */, + krb5_principal principal /* IN */, + krb5_keyblock **keyblocks /* OUT */, + int *n_keys /* OUT */) +{ + krb5_db_entry kdb; + osa_princ_ent_rec adb; + krb5_key_data *key_data; + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + krb5_keyblock *mkey_ptr; + + if (keyblocks) + *keyblocks = NULL; + + CHECK_HANDLE(server_handle); + + if (principal == NULL) + return EINVAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + if (keyblocks) { + if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, &kdb, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(handle->context, master_keylist); + master_keylist = tmp_mkey_list; + if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, + &kdb, &mkey_ptr))) { + goto done; + } + } else { + goto done; + } + } + + if (handle->api_version == KADM5_API_VERSION_1) { + /* Version 1 clients will expect to see a DES_CRC enctype. */ + if ((ret = krb5_dbe_find_enctype(handle->context, &kdb, + ENCTYPE_DES_CBC_CRC, + -1, -1, &key_data))) + goto done; + + if ((ret = decrypt_key_data(handle->context, mkey_ptr, 1, key_data, + keyblocks, NULL))) + goto done; + } else { + ret = decrypt_key_data(handle->context, mkey_ptr, + kdb.n_key_data, kdb.key_data, + keyblocks, n_keys); + if (ret) + goto done; + } + } + + ret = KADM5_OK; +done: + kdb_free_entry(handle, &kdb, &adb); + + 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 + * mkey, and if n_keys is not NULL fill it in with the + * number of keys decrypted. + */ +static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, + 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, mkey, + &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; + krb5_keyblock *mkey_ptr; + 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; + + /* find_mkey only uses this field */ + dbent.tl_data = entry->tl_data; + if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, &dbent, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock, 0, &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(handle->context, master_keylist); + master_keylist = tmp_mkey_list; + if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, + &dbent, &mkey_ptr))) { + return ret; + } + } else { + return ret; + } + } + + if ((ret = krb5_dbekd_decrypt_key_data(handle->context, + mkey_ptr, 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. + */ + if (ktype != -1) + keyblock->enctype = ktype; + + if (kvnop) + *kvnop = key_data->key_data_kvno; + + return KADM5_OK; +} diff --git a/krb5-1-7/src/lib/kadm5/str_conv.c b/krb5-1-7/src/lib/kadm5/str_conv.c new file mode 100644 index 000000000..2bd99adbc --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/str_conv.c @@ -0,0 +1,404 @@ +/* + * 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_ok_as_delegate_in[] = "ok-as-delegate"; +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_ok_as_delegate_out[] = "OK as Delegate"; +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_OK_AS_DELEGATE, 1, flags_ok_as_delegate_in, flags_ok_as_delegate_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 0) + krb5int_buf_add(&buf, sepstring); + krb5int_buf_add(&buf, flags_table[i].fl_output); + /* Keep track of what we matched */ + pflags |= flags_table[i].fl_flags; + } + } + if (krb5int_buf_data(&buf) == NULL) + return(ENOMEM); + + /* See if there's any leftovers */ + if (flags & ~pflags) + return(EINVAL); + + return(0); +} + +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(strlcpy(buffer, flags_table[flag].fl_specifier, buflen) >= buflen) + return ENOMEM; + 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 + * or + * + */ + sp = (char *) NULL; + /* Attempt to find a separator */ + septmp = ksseplist; + for (sp = strchr(kp, (int) *septmp); + *(++septmp) && !sp; + sp = 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)); + free(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 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-7/src/lib/kadm5/unit-test/api.0/destroy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/destroy.exp new file mode 100644 index 000000000..0f103991e --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/dlte-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/dlte-policy.exp new file mode 100644 index 000000000..cd82738e6 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/dlte-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/dlte-principal.exp new file mode 100644 index 000000000..5c617fb35 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/get-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/get-policy.exp new file mode 100644 index 000000000..7b0181412 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/get-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/get-principal.exp new file mode 100644 index 000000000..cf055f787 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/init.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/init.exp new file mode 100644 index 000000000..d39ecce07 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/mod-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/mod-policy.exp new file mode 100644 index 000000000..ec55999b7 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/mod-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/mod-principal.exp new file mode 100644 index 000000000..2d68a19c1 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/api.0/mod-principal.exp @@ -0,0 +1,1943 @@ +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" } + -re "null\n$prompt$" { pass "$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-7/src/lib/kadm5/unit-test/api.0/randkey-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/randkey-principal.exp new file mode 100644 index 000000000..c96700194 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.0/rename-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.0/rename-principal.exp new file mode 100644 index 000000000..d5f012f8b --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.1/lock.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.1/lock.exp new file mode 100644 index 000000000..02df75bf7 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp new file mode 100644 index 000000000..d249af0d9 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/chpass-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/chpass-principal.exp new file mode 100644 index 000000000..0571df20c --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-policy.exp new file mode 100644 index 000000000..2c42cb43f --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-policy.exp @@ -0,0 +1,956 @@ +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: (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-7/src/lib/kadm5/unit-test/api.2/crte-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-principal.exp new file mode 100644 index 000000000..2aa59deca --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/api.2/crte-principal.exp @@ -0,0 +1,1340 @@ +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 {! ((! [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_succeed_test [format { + kadm5_create_principal $server_handle [simple_principal "%s/a"] \ + {KADM5_PRINCIPAL} null + } $test] + 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-7/src/lib/kadm5/unit-test/api.2/destroy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/destroy.exp new file mode 100644 index 000000000..744cacd21 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/dlte-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/dlte-policy.exp new file mode 100644 index 000000000..c2a53182a --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/dlte-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/dlte-principal.exp new file mode 100644 index 000000000..f9dad7801 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/get-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/get-policy.exp new file mode 100644 index 000000000..83aef80e8 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp new file mode 100644 index 000000000..65c28b808 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/get-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/get-principal.exp new file mode 100644 index 000000000..f7a73078d --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/init-v2.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/init-v2.exp new file mode 100644 index 000000000..24bfb09b0 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/api.2/init-v2.exp @@ -0,0 +1,515 @@ +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 + } "KRB5_KDB_CANTREAD_STORED" +} +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 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-7/src/lib/kadm5/unit-test/api.2/init.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/init.exp new file mode 100644 index 000000000..335f6e041 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-policy.exp new file mode 100644 index 000000000..2cc168648 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp new file mode 100644 index 000000000..44c835e57 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/mod-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-principal.exp new file mode 100644 index 000000000..7c381c41a --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/api.2/mod-principal.exp @@ -0,0 +1,1943 @@ +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" } + -re "null\n$prompt$" { pass "$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-7/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp new file mode 100644 index 000000000..c9d1104bc --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/api.2/randkey-principal.exp b/krb5-1-7/src/lib/kadm5/unit-test/api.2/randkey-principal.exp new file mode 100644 index 000000000..ecf79e476 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kadm5/unit-test/config/unix.exp b/krb5-1-7/src/lib/kadm5/unit-test/config/unix.exp new file mode 100644 index 000000000..5cc83a0c8 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/config/unix.exp @@ -0,0 +1,220 @@ +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 +} + +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. +#&&![string match "/bin/sh" $arg] sh is used to start kadmind! + if [string match "/" [string index $arg 0]]&&![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 + } +} + +# 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 { perror "EOF starting API" } + timeout { perror "Timeout starting API" } + } + if {! [info exists env(TCLUTIL)]} { + perror "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 { perror "EOF starting API" } + timeout { perror "Timeout starting API" } + } + send "source $env(TCLUTIL)\n" + expect { + -re "$prompt$" {} + eof { perror "EOF starting API" } + timeout { perror "Timeout starting API" } + } + send "set current_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION &~ \$OVSEC_KADM_STRUCT_VERSION_MASK\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "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 { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set bad_struct_version_mask \[expr 0x65432100 | \$current_struct_version\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set bad_api_version_mask \[expr 0x65432100 | \$current_api_version\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set no_api_version_mask \$current_api_version\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set no_struct_version_mask \$current_struct_version\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set old_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0x00\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set old_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0x00\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set new_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0xca\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "timeout setting API varibles"} + } + send "set new_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0xca\]\n" + expect { + -re "$prompt$" {} + eof { perror "EOF setting API varibles"} + timeout { perror "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-7/src/lib/kadm5/unit-test/deps b/krb5-1-7/src/lib/kadm5/unit-test/deps new file mode 100644 index 000000000..8a58416f3 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/deps @@ -0,0 +1,82 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)init-test.$(OBJEXT): $(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/kdb.h \ + $(SRCTOP)/include/krb5.h init-test.c +$(OUTPRE)destroy-test.$(OBJEXT): $(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/kdb.h \ + $(SRCTOP)/include/krb5.h destroy-test.c +$(OUTPRE)handle-test.$(OBJEXT): $(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/kdb.h \ + $(SRCTOP)/include/krb5.h handle-test.c +$(OUTPRE)iter-test.$(OBJEXT): $(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/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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/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/kdb.h \ + $(SRCTOP)/include/krb5.h randkey-test.c +$(OUTPRE)lock-test.$(OBJEXT): $(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/kdb.h \ + $(SRCTOP)/include/krb5.h lock-test.c diff --git a/krb5-1-7/src/lib/kadm5/unit-test/destroy-test.c b/krb5-1-7/src/lib/kadm5/unit-test/destroy-test.c new file mode 100644 index 000000000..6d7435c45 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/destroy-test.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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-7/src/lib/kadm5/unit-test/diff-files/destroy-1 b/krb5-1-7/src/lib/kadm5/unit-test/diff-files/destroy-1 new file mode 100644 index 000000000..593d67320 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/diff-files/destroy-1 @@ -0,0 +1,2 @@ +##! nochanges + diff --git a/krb5-1-7/src/lib/kadm5/unit-test/diff-files/no-diffs b/krb5-1-7/src/lib/kadm5/unit-test/diff-files/no-diffs new file mode 100644 index 000000000..593d67320 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/diff-files/no-diffs @@ -0,0 +1,2 @@ +##! nochanges + diff --git a/krb5-1-7/src/lib/kadm5/unit-test/handle-test.c b/krb5-1-7/src/lib/kadm5/unit-test/handle-test.c new file mode 100644 index 000000000..3f723851d --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/handle-test.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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-7/src/lib/kadm5/unit-test/init-test.c b/krb5-1-7/src/lib/kadm5/unit-test/init-test.c new file mode 100644 index 000000000..575b24f35 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/init-test.c @@ -0,0 +1,30 @@ +#undef USE_KADM5_API_VERSION +#include +#include +#include +#include +#include +#include + +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-7/src/lib/kadm5/unit-test/iter-test.c b/krb5-1-7/src/lib/kadm5/unit-test/iter-test.c new file mode 100644 index 000000000..17e561ef1 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/iter-test.c @@ -0,0 +1,48 @@ +#include +#include +#include + +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-7/src/lib/kadm5/unit-test/lib/lib.t b/krb5-1-7/src/lib/kadm5/unit-test/lib/lib.t new file mode 100644 index 000000000..b4302304e --- /dev/null +++ b/krb5-1-7/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 + }]} { + perror "$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" { perror "$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" { perror "$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" { perror "$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" { perror "$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" { perror "$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" { perror "$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" { perror "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 { perror "waiting for kadmin.local prompt"; return 1} + } + send "ank -pw \"$name\" \"$name\"\n" + expect { + -re "Principal \"$name.*\" created." {} + "kadmin.local:" { + perror "expecting principal created message"; + return 1 + } + default { perror "waiting for principal created message"; return 1 } + } + expect { + "kadmin.local:" {} + default { perror "waiting for kadmin.local prompt"; return 1 } + } + close + wait + return 0 +} + + diff --git a/krb5-1-7/src/lib/kadm5/unit-test/lock-test.c b/krb5-1-7/src/lib/kadm5/unit-test/lock-test.c new file mode 100644 index 000000000..489b7b88e --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#include + +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-7/src/lib/kadm5/unit-test/randkey-test.c b/krb5-1-7/src/lib/kadm5/unit-test/randkey-test.c new file mode 100644 index 000000000..4b17bcb22 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/randkey-test.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include + +#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-7/src/lib/kadm5/unit-test/setkey-test.c b/krb5-1-7/src/lib/kadm5/unit-test/setkey-test.c new file mode 100644 index 000000000..865fc14b7 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/setkey-test.c @@ -0,0 +1,233 @@ +#include +#include +#include + +#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-7/src/lib/kadm5/unit-test/site.exp b/krb5-1-7/src/lib/kadm5/unit-test/site.exp new file mode 100644 index 000000000..18b435dd1 --- /dev/null +++ b/krb5-1-7/src/lib/kadm5/unit-test/site.exp @@ -0,0 +1,2 @@ +set tool ovsec_kadm_srv_tcl +set prompt "% " diff --git a/krb5-1-7/src/lib/kdb/Makefile.in b/krb5-1-7/src/lib/kdb/Makefile.in new file mode 100644 index 000000000..9c98679aa --- /dev/null +++ b/krb5-1-7/src/lib/kdb/Makefile.in @@ -0,0 +1,66 @@ +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)/libgssrpc$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) +SHLIB_EXPLIBS=-lgssrpc -lkrb5 -lk5crypto -lcom_err $(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)/iprop_xdr.c \ + $(srcdir)/kdb_convert.c \ + $(srcdir)/kdb_log.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 \ + iprop_xdr.o \ + kdb_convert.o \ + kdb_log.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 + +generate-files-mac: darwin.exports + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/kdb/adb_err.et b/krb5-1-7/src/lib/kdb/adb_err.et new file mode 100644 index 000000000..394802571 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/kdb/decrypt_key.c b/krb5-1-7/src/lib/kdb/decrypt_key.c new file mode 100644 index 000000000..a564c37b0 --- /dev/null +++ b/krb5-1-7/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_def_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))) { + free(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) { + free(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]) { + free(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-7/src/lib/kdb/deps b/krb5-1-7/src/lib/kdb/deps new file mode 100644 index 000000000..d99c72e20 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/deps @@ -0,0 +1,119 @@ +# +# Generated makefile dependencies follow. +# +kdb5.so kdb5.po $(OUTPRE)kdb5.$(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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/kdb_log.h \ + $(SRCTOP)/include/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 \ + kdb5int.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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 +iprop_xdr.so iprop_xdr.po $(OUTPRE)iprop_xdr.$(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/iprop.h iprop_xdr.c +kdb_convert.so kdb_convert.po $(OUTPRE)kdb_convert.$(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/iprop.h $(SRCTOP)/include/iprop_hdr.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_log.h \ + $(SRCTOP)/include/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_convert.c +kdb_log.so kdb_log.po $(OUTPRE)kdb_log.$(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/iprop.h \ + $(SRCTOP)/include/iprop_hdr.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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_ext.h $(SRCTOP)/include/kdb_log.h \ + $(SRCTOP)/include/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.h kdb5int.h kdb_log.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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-7/src/lib/kdb/encrypt_key.c b/krb5-1-7/src/lib/kdb/encrypt_key.c new file mode 100644 index 000000000..0db1a029a --- /dev/null +++ b/krb5-1-7/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_def_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]) + free(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))) { + free(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) { + free(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-7/src/lib/kdb/iprop.x b/krb5-1-7/src/lib/kdb/iprop.x new file mode 100644 index 000000000..840e7a2e5 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/iprop.x @@ -0,0 +1,223 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* %#pragma ident "@(#)iprop.x 1.2 04/02/20 SMI" */ + +/* + * Main source: + * lib/kdb/iprop.x + * + * Generated files: + * lib/kdb/iprop_xdr.c + * include/iprop.h + * slave/kpropd_rpc.c (clnt) + * + * Derived files: + * kadmin/server/ipropd_svc.c + */ + +#ifdef RPC_XDR +%#include "iprop.h" +#endif /* RPC_XDR */ + +/* + * Initial declarations + */ + +#ifndef RPC_HDR +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +/*typedef hyper int64_t;*/ +/*typedef unsigned hyper uint64_t;*/ +#endif /* !RPC_HDR */ + +typedef opaque utf8str_t<>; + +/* + * Transaction log serial no. + */ +typedef uint32_t kdb_sno_t; + +/* Timestamp */ +struct kdbe_time_t { + uint32_t seconds; + uint32_t useconds; +}; + +/* Key Data */ +struct kdbe_key_t { + int32_t k_ver; /* Version */ + int32_t k_kvno; /* Key version no. */ + int32_t k_enctype<>; + utf8str_t k_contents<>; +}; + +/* Content data */ +struct kdbe_data_t { + int32_t k_magic; + utf8str_t k_data; +}; + +/* Principal Data */ +struct kdbe_princ_t { + utf8str_t k_realm; + kdbe_data_t k_components<>; + int32_t k_nametype; +}; + +/* TL data (pre-auth specific data) */ +struct kdbe_tl_t { + int16_t tl_type; + opaque tl_data<>; +}; + +/* Structure to store pwd history */ +typedef kdbe_key_t kdbe_pw_hist_t<>; + +/* Basic KDB entry attributes */ +enum kdbe_attr_type_t { + AT_ATTRFLAGS = 0, + AT_MAX_LIFE = 1, + AT_MAX_RENEW_LIFE = 2, + AT_EXP = 3, + AT_PW_EXP = 4, + AT_LAST_SUCCESS = 5, + AT_LAST_FAILED = 6, + AT_FAIL_AUTH_COUNT = 7, + AT_PRINC = 8, + AT_KEYDATA = 9, + AT_TL_DATA = 10, + AT_LEN = 11, + AT_MOD_PRINC = 12, + AT_MOD_TIME = 13, + AT_MOD_WHERE = 14, + AT_PW_LAST_CHANGE = 15, + AT_PW_POLICY = 16, + AT_PW_POLICY_SWITCH = 17, + AT_PW_HIST_KVNO = 18, + AT_PW_HIST = 19 +}; + +/* KDB entry, Attribute=value */ +union kdbe_val_t switch (kdbe_attr_type_t av_type) { +case AT_ATTRFLAGS: + uint32_t av_attrflags; +case AT_MAX_LIFE: + uint32_t av_max_life; +case AT_MAX_RENEW_LIFE: + uint32_t av_max_renew_life; +case AT_EXP: + uint32_t av_exp; +case AT_PW_EXP: + uint32_t av_pw_exp; +case AT_LAST_SUCCESS: + uint32_t av_last_success; +case AT_LAST_FAILED: + uint32_t av_last_failed; +case AT_FAIL_AUTH_COUNT: + uint32_t av_fail_auth_count; +case AT_PRINC: + kdbe_princ_t av_princ; +case AT_KEYDATA: + kdbe_key_t av_keydata<>; /* array of keys */ +case AT_TL_DATA: + kdbe_tl_t av_tldata<>; /* array of TL data */ +case AT_LEN: + int16_t av_len; +case AT_PW_LAST_CHANGE: + uint32_t av_pw_last_change; +case AT_MOD_PRINC: + kdbe_princ_t av_mod_princ; +case AT_MOD_TIME: + uint32_t av_mod_time; +case AT_MOD_WHERE: + utf8str_t av_mod_where; +case AT_PW_POLICY: + utf8str_t av_pw_policy; +case AT_PW_POLICY_SWITCH: + bool av_pw_policy_switch; +case AT_PW_HIST_KVNO: + uint32_t av_pw_hist_kvno; +case AT_PW_HIST: + kdbe_pw_hist_t av_pw_hist<>; /* array of pw history */ +default: + opaque av_extension<>; /* futures */ +}; + +typedef kdbe_val_t kdbe_t<>; /* Array of attr/val makes a KDB entry */ + +/* + * Incremental update + */ +struct kdb_incr_update_t { + utf8str_t kdb_princ_name; /* Principal name */ + kdb_sno_t kdb_entry_sno; /* Serial # of entry */ + kdbe_time_t kdb_time; /* Timestamp of update */ + kdbe_t kdb_update; /* Attributes modified */ + bool kdb_deleted; /* Is this update a DELETION ? */ + bool kdb_commit; /* Is the entry committed or not ? */ + utf8str_t kdb_kdcs_seen_by<>; /* Names of slaves that have */ + /* seen this update - for */ + /* future use */ + opaque kdb_futures<>; /* futures */ +}; + +/* + * Update log body + */ +typedef kdb_incr_update_t kdb_ulog_t<>; + +enum update_status_t { + UPDATE_OK = 0, + UPDATE_ERROR = 1, + UPDATE_FULL_RESYNC_NEEDED = 2, + UPDATE_BUSY = 3, + UPDATE_NIL = 4, + UPDATE_PERM_DENIED = 5 +}; + +struct kdb_last_t { + kdb_sno_t last_sno; + kdbe_time_t last_time; +}; + +struct kdb_incr_result_t { + kdb_last_t lastentry; + kdb_ulog_t updates; + update_status_t ret; +}; + +struct kdb_fullresync_result_t { + kdb_last_t lastentry; + update_status_t ret; +}; + +program KRB5_IPROP_PROG { + version KRB5_IPROP_VERS { + /* + * NULL procedure + */ + void + IPROP_NULL(void) = 0; + + /* + * Keep waiting for and get next incremental update(s) + * + * Will return latest kdb_vers on the master (if different), + * alongwith return value and affected db entries. + */ + kdb_incr_result_t + IPROP_GET_UPDATES(kdb_last_t) = 1; + + /* + * We need to do the full-resync of the db, since the + * serial nos./timestamps are way out-of-whack + */ + kdb_fullresync_result_t + IPROP_FULL_RESYNC(void) = 2; + } = 1; +} = 100423; diff --git a/krb5-1-7/src/lib/kdb/iprop_xdr.c b/krb5-1-7/src/lib/kdb/iprop_xdr.c new file mode 100644 index 000000000..a8b7685ff --- /dev/null +++ b/krb5-1-7/src/lib/kdb/iprop_xdr.c @@ -0,0 +1,351 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "iprop.h" +#include "iprop.h" + +bool_t +xdr_int16_t (XDR *xdrs, int16_t *objp) +{ + register int32_t *buf; + + if (!xdr_short (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_uint16_t (XDR *xdrs, uint16_t *objp) +{ + register int32_t *buf; + + if (!xdr_u_short (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_int32_t (XDR *xdrs, int32_t *objp) +{ + register int32_t *buf; + + if (!xdr_int (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_uint32_t (XDR *xdrs, uint32_t *objp) +{ + register int32_t *buf; + + if (!xdr_u_int (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_utf8str_t (XDR *xdrs, utf8str_t *objp) +{ + register int32_t *buf; + + if (!xdr_bytes (xdrs, (char **)&objp->utf8str_t_val, (u_int *) &objp->utf8str_t_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_sno_t (XDR *xdrs, kdb_sno_t *objp) +{ + register int32_t *buf; + + if (!xdr_uint32_t (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_time_t (XDR *xdrs, kdbe_time_t *objp) +{ + register int32_t *buf; + + if (!xdr_uint32_t (xdrs, &objp->seconds)) + return FALSE; + if (!xdr_uint32_t (xdrs, &objp->useconds)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_key_t (XDR *xdrs, kdbe_key_t *objp) +{ + register int32_t *buf; + + if (!xdr_int32_t (xdrs, &objp->k_ver)) + return FALSE; + if (!xdr_int32_t (xdrs, &objp->k_kvno)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_enctype.k_enctype_val, (u_int *) &objp->k_enctype.k_enctype_len, ~0, + sizeof (int32_t), (xdrproc_t) xdr_int32_t)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_contents.k_contents_val, (u_int *) &objp->k_contents.k_contents_len, ~0, + sizeof (utf8str_t), (xdrproc_t) xdr_utf8str_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_data_t (XDR *xdrs, kdbe_data_t *objp) +{ + register int32_t *buf; + + if (!xdr_int32_t (xdrs, &objp->k_magic)) + return FALSE; + if (!xdr_utf8str_t (xdrs, &objp->k_data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_princ_t (XDR *xdrs, kdbe_princ_t *objp) +{ + register int32_t *buf; + + if (!xdr_utf8str_t (xdrs, &objp->k_realm)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_components.k_components_val, (u_int *) &objp->k_components.k_components_len, ~0, + sizeof (kdbe_data_t), (xdrproc_t) xdr_kdbe_data_t)) + return FALSE; + if (!xdr_int32_t (xdrs, &objp->k_nametype)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_tl_t (XDR *xdrs, kdbe_tl_t *objp) +{ + register int32_t *buf; + + if (!xdr_int16_t (xdrs, &objp->tl_type)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->tl_data.tl_data_val, (u_int *) &objp->tl_data.tl_data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_pw_hist_t (XDR *xdrs, kdbe_pw_hist_t *objp) +{ + register int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdbe_pw_hist_t_val, (u_int *) &objp->kdbe_pw_hist_t_len, ~0, + sizeof (kdbe_key_t), (xdrproc_t) xdr_kdbe_key_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_attr_type_t (XDR *xdrs, kdbe_attr_type_t *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_val_t (XDR *xdrs, kdbe_val_t *objp) +{ + register int32_t *buf; + + if (!xdr_kdbe_attr_type_t (xdrs, &objp->av_type)) + return FALSE; + switch (objp->av_type) { + case AT_ATTRFLAGS: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_attrflags)) + return FALSE; + break; + case AT_MAX_LIFE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_max_life)) + return FALSE; + break; + case AT_MAX_RENEW_LIFE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_max_renew_life)) + return FALSE; + break; + case AT_EXP: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_exp)) + return FALSE; + break; + case AT_PW_EXP: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_exp)) + return FALSE; + break; + case AT_LAST_SUCCESS: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_last_success)) + return FALSE; + break; + case AT_LAST_FAILED: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_last_failed)) + return FALSE; + break; + case AT_FAIL_AUTH_COUNT: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_fail_auth_count)) + return FALSE; + break; + case AT_PRINC: + if (!xdr_kdbe_princ_t (xdrs, &objp->kdbe_val_t_u.av_princ)) + return FALSE; + break; + case AT_KEYDATA: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_keydata.av_keydata_val, (u_int *) &objp->kdbe_val_t_u.av_keydata.av_keydata_len, ~0, + sizeof (kdbe_key_t), (xdrproc_t) xdr_kdbe_key_t)) + return FALSE; + break; + case AT_TL_DATA: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_tldata.av_tldata_val, (u_int *) &objp->kdbe_val_t_u.av_tldata.av_tldata_len, ~0, + sizeof (kdbe_tl_t), (xdrproc_t) xdr_kdbe_tl_t)) + return FALSE; + break; + case AT_LEN: + if (!xdr_int16_t (xdrs, &objp->kdbe_val_t_u.av_len)) + return FALSE; + break; + case AT_PW_LAST_CHANGE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_last_change)) + return FALSE; + break; + case AT_MOD_PRINC: + if (!xdr_kdbe_princ_t (xdrs, &objp->kdbe_val_t_u.av_mod_princ)) + return FALSE; + break; + case AT_MOD_TIME: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_mod_time)) + return FALSE; + break; + case AT_MOD_WHERE: + if (!xdr_utf8str_t (xdrs, &objp->kdbe_val_t_u.av_mod_where)) + return FALSE; + break; + case AT_PW_POLICY: + if (!xdr_utf8str_t (xdrs, &objp->kdbe_val_t_u.av_pw_policy)) + return FALSE; + break; + case AT_PW_POLICY_SWITCH: + if (!xdr_bool (xdrs, &objp->kdbe_val_t_u.av_pw_policy_switch)) + return FALSE; + break; + case AT_PW_HIST_KVNO: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_hist_kvno)) + return FALSE; + break; + case AT_PW_HIST: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_pw_hist.av_pw_hist_val, (u_int *) &objp->kdbe_val_t_u.av_pw_hist.av_pw_hist_len, ~0, + sizeof (kdbe_pw_hist_t), (xdrproc_t) xdr_kdbe_pw_hist_t)) + return FALSE; + break; + default: + if (!xdr_bytes (xdrs, (char **)&objp->kdbe_val_t_u.av_extension.av_extension_val, (u_int *) &objp->kdbe_val_t_u.av_extension.av_extension_len, ~0)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_kdbe_t (XDR *xdrs, kdbe_t *objp) +{ + register int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdbe_t_val, (u_int *) &objp->kdbe_t_len, ~0, + sizeof (kdbe_val_t), (xdrproc_t) xdr_kdbe_val_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_incr_update_t (XDR *xdrs, kdb_incr_update_t *objp) +{ + register int32_t *buf; + + if (!xdr_utf8str_t (xdrs, &objp->kdb_princ_name)) + return FALSE; + if (!xdr_kdb_sno_t (xdrs, &objp->kdb_entry_sno)) + return FALSE; + if (!xdr_kdbe_time_t (xdrs, &objp->kdb_time)) + return FALSE; + if (!xdr_kdbe_t (xdrs, &objp->kdb_update)) + return FALSE; + if (!xdr_bool (xdrs, &objp->kdb_deleted)) + return FALSE; + if (!xdr_bool (xdrs, &objp->kdb_commit)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val, (u_int *) &objp->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len, ~0, + sizeof (utf8str_t), (xdrproc_t) xdr_utf8str_t)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->kdb_futures.kdb_futures_val, (u_int *) &objp->kdb_futures.kdb_futures_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_ulog_t (XDR *xdrs, kdb_ulog_t *objp) +{ + register int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdb_ulog_t_val, (u_int *) &objp->kdb_ulog_t_len, ~0, + sizeof (kdb_incr_update_t), (xdrproc_t) xdr_kdb_incr_update_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_update_status_t (XDR *xdrs, update_status_t *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_last_t (XDR *xdrs, kdb_last_t *objp) +{ + register int32_t *buf; + + if (!xdr_kdb_sno_t (xdrs, &objp->last_sno)) + return FALSE; + if (!xdr_kdbe_time_t (xdrs, &objp->last_time)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_incr_result_t (XDR *xdrs, kdb_incr_result_t *objp) +{ + register int32_t *buf; + + if (!xdr_kdb_last_t (xdrs, &objp->lastentry)) + return FALSE; + if (!xdr_kdb_ulog_t (xdrs, &objp->updates)) + return FALSE; + if (!xdr_update_status_t (xdrs, &objp->ret)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_fullresync_result_t (XDR *xdrs, kdb_fullresync_result_t *objp) +{ + register int32_t *buf; + + if (!xdr_kdb_last_t (xdrs, &objp->lastentry)) + return FALSE; + if (!xdr_update_status_t (xdrs, &objp->ret)) + return FALSE; + return TRUE; +} diff --git a/krb5-1-7/src/lib/kdb/kdb5.c b/krb5-1-7/src/lib/kdb/kdb5.c new file mode 100644 index 000000000..ed85d89a6 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb5.c @@ -0,0 +1,3117 @@ +/* + * Copyright 2006, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This code was based on code donated to MIT by Novell for + * distribution under the MIT license. + */ + +/* + * Include files + */ + +#include +#include +#include +#include +#include "kdb5.h" +#include +#include "kdb_log.h" +#include "kdb5int.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); +} + +/* + * XXX eventually this should be consolidated with krb5_free_key_data_contents + * so there is only a single version. + */ +void +krb5_dbe_free_key_data_contents(krb5_context context, krb5_key_data *key) +{ + int i, idx; + + if (key) { + idx = (key->key_data_ver == 1 ? 1 : 2); + for (i = 0; i < idx; i++) { + if (key->key_data_contents[i]) { + zap(key->key_data_contents[i], key->key_data_length[i]); + free(key->key_data_contents[i]); + } + } + } + return; +} + +void +krb5_dbe_free_key_list(krb5_context context, krb5_keylist_node *val) +{ + krb5_keylist_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + krb5_free_keyblock_contents(context, &(prev->keyblock)); + krb5_xfree(prev); + } +} + +void +krb5_dbe_free_actkvno_list(krb5_context context, krb5_actkvno_node *val) +{ + krb5_actkvno_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + krb5_xfree(prev); + } +} + +void +krb5_dbe_free_mkey_aux_list(krb5_context context, krb5_mkey_aux_node *val) +{ + krb5_mkey_aux_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + krb5_dbe_free_key_data_contents(context, &prev->latest_mkey); + krb5_xfree(prev); + } +} + +void +krb5_dbe_free_tl_data(krb5_context context, krb5_tl_data *tl_data) +{ + if (tl_data) { + if (tl_data->tl_data_contents) + free(tl_data->tl_data_contents); + free(tl_data); + } +} + +#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.set_master_key_list == NULL) { + lib->vftabl.set_master_key_list = kdb_def_set_mkey_list; + } + + if (lib->vftabl.get_master_key == NULL) { + lib->vftabl.get_master_key = kdb_def_get_mkey; + } + + if (lib->vftabl.get_master_key_list == NULL) { + lib->vftabl.get_master_key_list = kdb_def_get_mkey_list; + } + + 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.fetch_master_key_list == NULL) { + lib->vftabl.fetch_master_key_list = krb5_def_fetch_mkey_list; + } + + if (lib->vftabl.store_master_key_list == NULL) { + lib->vftabl.store_master_key_list = krb5_def_store_mkey_list; + } + + 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; + } + + if (lib->vftabl.dbekd_decrypt_key_data == NULL) { + lib->vftabl.dbekd_decrypt_key_data = krb5_dbekd_def_decrypt_key_data; + } + + if (lib->vftabl.dbekd_encrypt_key_data == NULL) { + lib->vftabl.dbekd_encrypt_key_data = krb5_dbekd_def_encrypt_key_data; + } +} + +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; + } + + strlcpy((*lib)->name, lib_name, sizeof((*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 + { + snprintf(buf, sizeof(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 */ + snprintf(buf, sizeof(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, KRB5_CONF_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; + } + + strlcpy((*lib)->name, lib_name, sizeof((*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 = ENOMEM; + 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))) { + const 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))) { + const 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; +} + +krb5_error_code +krb5_db_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->dal_handle = 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(kcontext->dal_handle->lib_handle); + if (status) { + goto clean_n_exit; + } + + free(kcontext->dal_handle); + kcontext->dal_handle = 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->dal_handle != NULL); + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle && + kcontext->dal_handle->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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + /* module not loaded. So nothing to be done */ + goto clean_n_exit; + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + /* 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + /* 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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, 0, + 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_get_principal_ext(krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry * entries, + int *nentries, krb5_boolean * more) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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, + flags, + entries, nentries, + more); + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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; +} + +static void +free_db_args(krb5_context kcontext, char **db_args) +{ + int i; + if (db_args) { + /* XXX Is this right? Or are we borrowing storage from + the caller? */ + for (i = 0; db_args[i]; i++) + krb5_db_free(kcontext, db_args[i]); + free(db_args); + } +} + +static krb5_error_code +extract_db_args_from_tl_data(krb5_context kcontext, + krb5_tl_data **start, krb5_int16 *count, + char ***db_argsp) +{ + char **db_args = NULL; + int db_args_size = 0; + krb5_tl_data *prev, *curr, *next; + krb5_error_code status; + + /* 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 separate argument. Currently supports only one + principal, but passing it as a separate argument makes it + difficult for kadmin remote to pass arguments to server. */ + prev = NULL, curr = *start; + 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 */ + *start = curr->tl_data_next; + } else { + prev->tl_data_next = curr->tl_data_next; + } + (*count)--; + krb5_db_free(kcontext, curr); + + /* previous does not change */ + curr = next; + } else { + prev = curr; + curr = curr->tl_data_next; + } + } + status = 0; +clean_n_exit: + if (status != 0) { + free_db_args(kcontext, db_args); + db_args = NULL; + } + *db_argsp = db_args; + return status; +} + +krb5_error_code +krb5int_put_principal_no_log(krb5_context kcontext, + krb5_db_entry *entries, int *nentries) +{ + kdb5_dal_handle *dal_handle; + krb5_error_code status; + char **db_args; + + status = extract_db_args_from_tl_data(kcontext, &entries->tl_data, + &entries->n_tl_data, + &db_args); + if (status) + return status; + assert (kcontext->dal_handle != NULL); /* XXX */ + dal_handle = kcontext->dal_handle; + /* XXX Locking? */ + status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries, + nentries, + db_args); + get_errmsg(kcontext, status); + free_db_args(kcontext, db_args); + 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; + kdb_incr_update_t *upd, *fupd = 0; + char *princ_name = NULL; + kdb_log_context *log_ctx; + int i; + int ulog_locked = 0; + + log_ctx = kcontext->kdblog_context; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + status = extract_db_args_from_tl_data(kcontext, &entries->tl_data, + &entries->n_tl_data, + &db_args); + if (status) + goto clean_n_exit; + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + /* + * We need the lock since ulog_conv_2logentry() does a get + */ + if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { + if (!(upd = (kdb_incr_update_t *) + malloc(sizeof (kdb_incr_update_t)* *nentries))) { + status = errno; + goto err_lock; + } + fupd = upd; + + (void) memset(upd, 0, sizeof(kdb_incr_update_t)* *nentries); + + if ((status = ulog_conv_2logentry(kcontext, entries, upd, *nentries))) { + goto err_lock; + } + } + + status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE); + if (status != 0) + goto err_lock; + ulog_locked = 1; + + for (i = 0; i < *nentries; i++) { + /* + * We'll be sharing the same locks as db for logging + */ + if (fupd) { + if ((status = krb5_unparse_name(kcontext, entries->princ, + &princ_name))) + goto err_lock; + + upd->kdb_princ_name.utf8str_t_val = princ_name; + upd->kdb_princ_name.utf8str_t_len = strlen(princ_name); + + if ((status = ulog_add_update(kcontext, upd)) != 0) + goto err_lock; + upd++; + } + } + + status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries, + nentries, + db_args); + get_errmsg(kcontext, status); + if (status == 0 && fupd) { + upd = fupd; + for (i = 0; i < *nentries; i++) { + (void) ulog_finish_update(kcontext, upd); + upd++; + } + } +err_lock: + if (ulog_locked) + ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK); + + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + clean_n_exit: + free_db_args(kcontext, db_args); + + if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) + ulog_free_entries(fupd, *nentries); + + return status; +} + +krb5_error_code +krb5int_delete_principal_no_log(krb5_context kcontext, + krb5_principal search_for, + int *nentries) +{ + kdb5_dal_handle *dal_handle; + krb5_error_code status; + + assert (kcontext->dal_handle != NULL); /* XXX */ + + dal_handle = kcontext->dal_handle; + /* XXX Locking? */ + status = dal_handle->lib_handle->vftabl.db_delete_principal(kcontext, + search_for, + nentries); + get_errmsg(kcontext, status); + 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; + kdb_incr_update_t upd; + char *princ_name = NULL; + kdb_log_context *log_ctx; + + log_ctx = kcontext->kdblog_context; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE); + if (status) { + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + return status; + } + + /* + * We'll be sharing the same locks as db for logging + */ + if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { + if ((status = krb5_unparse_name(kcontext, search_for, &princ_name))) { + ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK); + (void) kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + return status; + } + + (void) memset(&upd, 0, sizeof (kdb_incr_update_t)); + + upd.kdb_princ_name.utf8str_t_val = princ_name; + upd.kdb_princ_name.utf8str_t_len = strlen(princ_name); + + if ((status = ulog_delete_update(kcontext, &upd)) != 0) { + ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK); + free(princ_name); + (void) kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + return status; + } + + free(princ_name); + } + + status = dal_handle->lib_handle->vftabl.db_delete_principal(kcontext, + search_for, + nentries); + get_errmsg(kcontext, status); + + /* + * We need to commit our update upon success + */ + if (!status) + if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) + (void) ulog_finish_update(kcontext, &upd); + + ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK); + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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_set_mkey_list(krb5_context kcontext, + krb5_keylist_node * keylist) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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_list(kcontext, keylist); + get_errmsg(kcontext, status); + + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + +clean_n_exit: + return status; +} + +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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + /* Let's 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_get_mkey_list(krb5_context kcontext, krb5_keylist_node ** keylist) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + /* Let's 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_list(kcontext, keylist); + get_errmsg(kcontext, status); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + +clean_n_exit: + return status; +} + +krb5_error_code +krb5_db_fetch_mkey_list(krb5_context context, + krb5_principal mname, + const krb5_keyblock * mkey, + krb5_kvno mkvno, + krb5_keylist_node **mkey_list) +{ + kdb5_dal_handle *dal_handle; + krb5_error_code status = 0; + + if (context->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(context); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = context->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + status = dal_handle->lib_handle->vftabl.fetch_master_key_list(context, + mname, + mkey, + mkvno, + mkey_list); + get_errmsg(context, status); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + if (status) { + goto clean_n_exit; + } + +clean_n_exit: + return status; +} + +krb5_error_code +krb5_db_free_mkey_list(krb5_context context, + krb5_keylist_node *mkey_list) +{ + krb5_keylist_node *cur, *prev; + + for (cur = mkey_list; cur != NULL;) { + prev = cur; + cur = cur->next; + krb5_free_keyblock_contents(context, &prev->keyblock); + krb5_xfree(prev); + } + + return 0; +} + +krb5_error_code +krb5_db_store_master_key(krb5_context kcontext, + char *keyfile, + krb5_principal mname, + krb5_kvno kvno, + krb5_keyblock * key, char *master_pwd) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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, + keyfile, + mname, + kvno, + key, master_pwd); + 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_list(krb5_context kcontext, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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_list(kcontext, + keyfile, + mname, + keylist, + 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_kvno * kvno, + krb5_data * salt, + krb5_keyblock * key) +{ + krb5_error_code retval; + char password[BUFSIZ]; + krb5_data pwd; + unsigned int size = sizeof(password); + 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 a kvno pointer was passed in and it dereferences the IGNORE_VNO + * value then it should be assigned the value of the kvno associated + * with the current mkey princ key if that princ entry is available + * otherwise assign 1 which is the default kvno value for the mkey + * princ. + */ + if (kvno != NULL && *kvno == IGNORE_VNO) { + int nentries = 1; + krb5_boolean more; + krb5_error_code rc; + krb5_db_entry master_entry; + + rc = krb5_db_get_principal(context, mname, + &master_entry, &nentries, &more); + + if (rc == 0 && nentries == 1 && more == FALSE) + *kvno = (krb5_kvno) master_entry.key_data->key_data_kvno; + else + *kvno = 1; + + if (rc == 0 && nentries) + krb5_db_free_principal(context, &master_entry, nentries); + } + + if (!salt) + free(scratch.data); + zap(password, sizeof(password)); /* erase it */ + + } else { + kdb5_dal_handle *dal_handle; + + if (context->dal_handle == NULL) { + retval = krb5_db_setup_lib_handle(context); + if (retval) { + goto clean_n_exit; + } + } + + dal_handle = context->dal_handle; + retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (retval) { + goto clean_n_exit; + } + + /* get the enctype from the stash */ + tmp_key.enctype = ENCTYPE_UNKNOWN; + + 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) { + zap(tmp_key.contents, 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_kvno kvno, + krb5_keyblock * mkey) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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, + kvno, + mkey); + get_errmsg(kcontext, status); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + clean_n_exit: + return status; +} + +krb5_error_code +krb5_dbe_fetch_act_key_list(krb5_context context, + krb5_principal princ, + krb5_actkvno_node **act_key_list) +{ + krb5_error_code retval = 0; + krb5_db_entry entry; + int nprinc; + krb5_boolean more; + + if (act_key_list == NULL) + return (EINVAL); + + nprinc = 1; + if ((retval = krb5_db_get_principal(context, princ, &entry, + &nprinc, &more))) { + return (retval); + } + + if (nprinc != 1) { + if (nprinc) { + krb5_db_free_principal(context, &entry, nprinc); + return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + } else { + return(KRB5_KDB_NOMASTERKEY); + } + } else if (more) { + krb5_db_free_principal(context, &entry, nprinc); + return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + } + + retval = krb5_dbe_lookup_actkvno(context, &entry, act_key_list); + + if (*act_key_list == NULL) { + krb5_actkvno_node *tmp_actkvno; + /* + * for mkey princ entries without KRB5_TL_ACTKVNO data provide a default + */ + + tmp_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node)); + if (tmp_actkvno == NULL) + return (ENOMEM); + + memset(tmp_actkvno, 0, sizeof(krb5_actkvno_node)); + tmp_actkvno->act_time = 0; /* earliest time possible */ + /* use most current key */ + tmp_actkvno->act_kvno = entry.key_data[0].key_data_kvno; + *act_key_list = tmp_actkvno; + } + + krb5_db_free_principal(context, &entry, nprinc); + return retval; +} + +/* + * Locates the "active" mkey used when encrypting a princ's keys. Note, the + * caller must NOT free the output act_mkey. + */ + +krb5_error_code +krb5_dbe_find_act_mkey(krb5_context context, + krb5_keylist_node *mkey_list, + krb5_actkvno_node *act_mkey_list, + krb5_kvno *act_kvno, + krb5_keyblock **act_mkey) +{ + krb5_kvno tmp_act_kvno; + krb5_error_code retval; + krb5_keylist_node *cur_keyblock = mkey_list; + krb5_actkvno_node *prev_actkvno, *cur_actkvno; + krb5_timestamp now; + krb5_boolean found = FALSE; + + if ((retval = krb5_timeofday(context, &now))) + return (retval); + + /* + * The list should be sorted in time, early to later so if the first entry + * is later than now, this is a problem. The fallback in this case is to + * return the earlist activation entry. + */ + if (act_mkey_list->act_time > now) { + while (cur_keyblock && cur_keyblock->kvno != act_mkey_list->act_kvno) + cur_keyblock = cur_keyblock->next; + if (cur_keyblock) { + *act_mkey = &cur_keyblock->keyblock; + if (act_kvno != NULL) + *act_kvno = cur_keyblock->kvno; + return (0); + } else { + return (KRB5_KDB_NOACTMASTERKEY); + } + } + + /* find the most current entry <= now */ + for (prev_actkvno = cur_actkvno = act_mkey_list; cur_actkvno != NULL; + prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { + + if (cur_actkvno->act_time == now) { + tmp_act_kvno = cur_actkvno->act_kvno; + found = TRUE; + break; + } else if (cur_actkvno->act_time > now && prev_actkvno->act_time <= now) { + tmp_act_kvno = prev_actkvno->act_kvno; + found = TRUE; + break; + } + } + + if (!found) { + /* + * The end of the list was encountered and all entries are < now so use + * the latest entry. + */ + if (prev_actkvno->act_time <= now) { + tmp_act_kvno = prev_actkvno->act_kvno; + } else { + /* XXX this shouldn't happen */ + return (KRB5_KDB_NOACTMASTERKEY); + } + } + + while (cur_keyblock && cur_keyblock->kvno != tmp_act_kvno) + cur_keyblock = cur_keyblock->next; + + if (cur_keyblock) { + *act_mkey = &cur_keyblock->keyblock; + if (act_kvno != NULL) + *act_kvno = tmp_act_kvno; + return (0); + } else { + return (KRB5_KDB_NO_MATCHING_KEY); + } +} + +/* + * Locates the mkey used to protect a princ's keys. Note, the caller must not + * free the output key. + */ +krb5_error_code +krb5_dbe_find_mkey(krb5_context context, + krb5_keylist_node * mkey_list, + krb5_db_entry * entry, + krb5_keyblock ** mkey) +{ + krb5_kvno mkvno; + krb5_error_code retval; + krb5_keylist_node *cur_keyblock = mkey_list; + + retval = krb5_dbe_lookup_mkvno(context, entry, &mkvno); + if (retval) + return (retval); + + while (cur_keyblock && cur_keyblock->kvno != mkvno) + cur_keyblock = cur_keyblock->next; + + if (cur_keyblock) { + *mkey = &cur_keyblock->keyblock; + return (0); + } else { + return (KRB5_KDB_NO_MATCHING_KEY); + } +} + +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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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; + char *fname; + + if (!keyname) + keyname = KRB5_KDB_M_NAME; /* XXX external? */ + + if (asprintf(&fname, "%s%s%s", keyname, REALM_SEP_STRING, realm) < 0) + return ENOMEM; + + 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; + + *mod_princ = NULL; + *mod_time = 0; + + 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_lookup_mkvno(krb5_context context, + krb5_db_entry *entry, + krb5_kvno *mkvno) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int16 tmp; + + tl_data.tl_data_type = KRB5_TL_MKVNO; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_length == 0) { + *mkvno = 1; /* default for princs that lack the KRB5_TL_MKVNO data */ + return (0); + } else if (tl_data.tl_data_length != 2) { + return (KRB5_KDB_TRUNCATED_RECORD); + } + + krb5_kdb_decode_int16(tl_data.tl_data_contents, tmp); + *mkvno = (krb5_kvno) tmp; + return (0); +} + +krb5_error_code +krb5_dbe_update_mkvno(krb5_context context, + krb5_db_entry * entry, + krb5_kvno mkvno) +{ + krb5_tl_data tl_data; + krb5_octet buf[2]; /* this is the encoded size of an int16 */ + krb5_int16 tmp_kvno = (krb5_int16) mkvno; + + tl_data.tl_data_type = KRB5_TL_MKVNO; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int16(tmp_kvno, buf); + tl_data.tl_data_contents = buf; + + return (krb5_dbe_update_tl_data(context, entry, &tl_data)); +} + +krb5_error_code +krb5_dbe_lookup_mkey_aux(krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node ** mkey_aux_data_list) +{ + krb5_tl_data tl_data; + krb5_int16 version; + krb5_mkey_aux_node *head_data = NULL, *new_data = NULL, + *prev_data = NULL; + krb5_octet *curloc; /* current location pointer */ + krb5_error_code code; + + tl_data.tl_data_type = KRB5_TL_MKEY_AUX; + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_contents == NULL) { + *mkey_aux_data_list = NULL; + return (0); + } else { + /* get version to determine how to parse the data */ + krb5_kdb_decode_int16(tl_data.tl_data_contents, version); + if (version == 1) { + /* variable size, must be at least 10 bytes */ + if (tl_data.tl_data_length < 10) + return (KRB5_KDB_TRUNCATED_RECORD); + + /* curloc points to first tuple entry in the tl_data_contents */ + curloc = tl_data.tl_data_contents + sizeof(version); + + while (curloc < (tl_data.tl_data_contents + tl_data.tl_data_length)) { + + new_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (new_data == NULL) { + krb5_dbe_free_mkey_aux_list(context, head_data); + return (ENOMEM); + } + memset(new_data, 0, sizeof(krb5_mkey_aux_node)); + + krb5_kdb_decode_int16(curloc, new_data->mkey_kvno); + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_kvno); + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_type[0]); + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_length[0]); + curloc += sizeof(krb5_ui_2); + + new_data->latest_mkey.key_data_contents[0] = (krb5_octet *) + malloc(new_data->latest_mkey.key_data_length[0]); + + if (new_data->latest_mkey.key_data_contents[0] == NULL) { + krb5_dbe_free_mkey_aux_list(context, head_data); + free(new_data); + return (ENOMEM); + } + memcpy(new_data->latest_mkey.key_data_contents[0], curloc, + new_data->latest_mkey.key_data_length[0]); + curloc += new_data->latest_mkey.key_data_length[0]; + + /* always using key data ver 1 for mkeys */ + new_data->latest_mkey.key_data_ver = 1; + + new_data->next = NULL; + if (prev_data != NULL) + prev_data->next = new_data; + else + head_data = new_data; + prev_data = new_data; + } + } else { + krb5_set_error_message(context, KRB5_KDB_BAD_VERSION, + "Illegal version number for KRB5_TL_MKEY_AUX %d\n", + version); + return (KRB5_KDB_BAD_VERSION); + } + } + *mkey_aux_data_list = head_data; + return (0); +} + +#if KRB5_TL_MKEY_AUX_VER == 1 +krb5_error_code +krb5_dbe_update_mkey_aux(krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node * mkey_aux_data_list) +{ + krb5_tl_data tl_data; + krb5_int16 version, tmp_kvno; + unsigned char *nextloc; + krb5_mkey_aux_node *aux_data_entry; + + if (!mkey_aux_data_list) { + /* delete the KRB5_TL_MKEY_AUX from the entry */ + krb5_dbe_delete_tl_data(context, entry, KRB5_TL_MKEY_AUX); + return (0); + } + + memset(&tl_data, 0, sizeof(tl_data)); + tl_data.tl_data_type = KRB5_TL_MKEY_AUX; + /* + * determine out how much space to allocate. Note key_data_ver not stored + * as this is hard coded to one and is accounted for in + * krb5_dbe_lookup_mkey_aux. + */ + tl_data.tl_data_length = sizeof(version); /* version */ + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + tl_data.tl_data_length += (sizeof(krb5_ui_2) + /* mkey_kvno */ + sizeof(krb5_ui_2) + /* latest_mkey kvno */ + sizeof(krb5_ui_2) + /* latest_mkey enctype */ + sizeof(krb5_ui_2) + /* latest_mkey length */ + aux_data_entry->latest_mkey.key_data_length[0]); + } + + tl_data.tl_data_contents = (krb5_octet *) malloc(tl_data.tl_data_length); + if (tl_data.tl_data_contents == NULL) { + return (ENOMEM); + } + + nextloc = tl_data.tl_data_contents; + version = KRB5_TL_MKEY_AUX_VER; + krb5_kdb_encode_int16(version, nextloc); + nextloc += sizeof(krb5_ui_2); + + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + tmp_kvno = (krb5_int16) aux_data_entry->mkey_kvno; + krb5_kdb_encode_int16(tmp_kvno, nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_kvno, + nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_type[0], + nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_length[0], + nextloc); + nextloc += sizeof(krb5_ui_2); + + if (aux_data_entry->latest_mkey.key_data_length[0] > 0) { + memcpy(nextloc, aux_data_entry->latest_mkey.key_data_contents[0], + aux_data_entry->latest_mkey.key_data_length[0]); + nextloc += aux_data_entry->latest_mkey.key_data_length[0]; + } + } + + return (krb5_dbe_update_tl_data(context, entry, &tl_data)); +} +#endif /* KRB5_TL_MKEY_AUX_VER == 1 */ + +#if KRB5_TL_ACTKVNO_VER == 1 +/* + * If version of the KRB5_TL_ACTKVNO data is KRB5_TL_ACTKVNO_VER == 1 then size of + * a actkvno tuple {act_kvno, act_time} entry is: + */ +#define ACTKVNO_TUPLE_SIZE (sizeof(krb5_int16) + sizeof(krb5_int32)) +#define act_kvno(cp) (cp) /* return pointer to start of act_kvno data */ +#define act_time(cp) ((cp) + sizeof(krb5_int16)) /* return pointer to start of act_time data */ +#endif + +krb5_error_code +krb5_dbe_lookup_actkvno(krb5_context context, + krb5_db_entry *entry, + krb5_actkvno_node **actkvno_list) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int16 version, tmp_kvno; + krb5_actkvno_node *head_data = NULL, *new_data = NULL, *prev_data = NULL; + unsigned int num_actkvno, i; + krb5_octet *next_tuple; + + memset(&tl_data, 0, sizeof(tl_data)); + tl_data.tl_data_type = KRB5_TL_ACTKVNO; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_contents == NULL) { + *actkvno_list = NULL; + return (0); + } else { + /* get version to determine how to parse the data */ + krb5_kdb_decode_int16(tl_data.tl_data_contents, version); + if (version == 1) { + + /* variable size, must be at least 8 bytes */ + if (tl_data.tl_data_length < 8) + return (KRB5_KDB_TRUNCATED_RECORD); + + /* + * Find number of tuple entries, remembering to account for version + * field. + */ + num_actkvno = (tl_data.tl_data_length - sizeof(version)) / + ACTKVNO_TUPLE_SIZE; + prev_data = NULL; + /* next_tuple points to first tuple entry in the tl_data_contents */ + next_tuple = tl_data.tl_data_contents + sizeof(version); + for (i = 0; i < num_actkvno; i++) { + new_data = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node)); + if (new_data == NULL) { + krb5_dbe_free_actkvno_list(context, head_data); + return (ENOMEM); + } + memset(new_data, 0, sizeof(krb5_actkvno_node)); + + /* using tmp_kvno to avoid type mismatch */ + krb5_kdb_decode_int16(act_kvno(next_tuple), tmp_kvno); + new_data->act_kvno = (krb5_kvno) tmp_kvno; + krb5_kdb_decode_int32(act_time(next_tuple), new_data->act_time); + + if (prev_data != NULL) + prev_data->next = new_data; + else + head_data = new_data; + prev_data = new_data; + next_tuple += ACTKVNO_TUPLE_SIZE; + } + } else { + krb5_set_error_message (context, KRB5_KDB_BAD_VERSION, + "Illegal version number for KRB5_TL_ACTKVNO %d\n", + version); + return (KRB5_KDB_BAD_VERSION); + } + } + *actkvno_list = head_data; + return (0); +} + +/* + * Add KRB5_TL_ACTKVNO TL data entries to krb5_db_entry *entry + */ +#if KRB5_TL_ACTKVNO_VER == 1 +krb5_error_code +krb5_dbe_update_actkvno(krb5_context context, + krb5_db_entry *entry, + const krb5_actkvno_node *actkvno_list) +{ + krb5_error_code retval = 0; + krb5_int16 version, tmp_kvno; + krb5_tl_data new_tl_data; + unsigned char *nextloc; + const krb5_actkvno_node *cur_actkvno; + krb5_octet *tmpptr; + + if (actkvno_list == NULL) { + return (EINVAL); + } + + memset(&new_tl_data, 0, sizeof(new_tl_data)); + /* allocate initial KRB5_TL_ACTKVNO tl_data entry */ + new_tl_data.tl_data_length = sizeof(version); + new_tl_data.tl_data_contents = (krb5_octet *) malloc(new_tl_data.tl_data_length); + if (new_tl_data.tl_data_contents == NULL) + return (ENOMEM); + + /* add the current version # for the data format used for KRB5_TL_ACTKVNO */ + version = KRB5_TL_ACTKVNO_VER; + krb5_kdb_encode_int16(version, (unsigned char *) new_tl_data.tl_data_contents); + + for (cur_actkvno = actkvno_list; cur_actkvno != NULL; + cur_actkvno = cur_actkvno->next) { + + new_tl_data.tl_data_length += ACTKVNO_TUPLE_SIZE; + tmpptr = realloc(new_tl_data.tl_data_contents, new_tl_data.tl_data_length); + if (tmpptr == NULL) { + free(new_tl_data.tl_data_contents); + return (ENOMEM); + } else { + new_tl_data.tl_data_contents = tmpptr; + } + + /* + * Using realloc so tl_data_contents is required to correctly calculate + * next location to store new tuple. + */ + nextloc = new_tl_data.tl_data_contents + new_tl_data.tl_data_length - ACTKVNO_TUPLE_SIZE; + /* using tmp_kvno to avoid type mismatch issues */ + tmp_kvno = (krb5_int16) cur_actkvno->act_kvno; + krb5_kdb_encode_int16(tmp_kvno, nextloc); + nextloc += sizeof(krb5_ui_2); + krb5_kdb_encode_int32((krb5_ui_4)cur_actkvno->act_time, nextloc); + } + + new_tl_data.tl_data_type = KRB5_TL_ACTKVNO; + retval = krb5_dbe_update_tl_data(context, entry, &new_tl_data); + free(new_tl_data.tl_data_contents); + + return (retval); +} +#endif /* KRB5_TL_ACTKVNO_VER == 1 */ + +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_delete_tl_data(krb5_context context, + krb5_db_entry *entry, + krb5_int16 tl_data_type) +{ + krb5_tl_data *tl_data, *prev_tl_data, *free_tl_data; + + /* + * Find existing entries of the specified type and remove them from the + * entry's tl_data list. + */ + + for (prev_tl_data = tl_data = entry->tl_data; tl_data != NULL;) { + if (tl_data->tl_data_type == tl_data_type) { + if (tl_data == entry->tl_data) { + /* remove from head */ + entry->tl_data = tl_data->tl_data_next; + prev_tl_data = entry->tl_data; + } else if (tl_data->tl_data_next == NULL) { + /* remove from tail */ + prev_tl_data->tl_data_next = NULL; + } else { + /* remove in between */ + prev_tl_data->tl_data_next = tl_data->tl_data_next; + } + free_tl_data = tl_data; + tl_data = tl_data->tl_data_next; + krb5_dbe_free_tl_data(context, free_tl_data); + entry->n_tl_data--; + } else { + prev_tl_data = tl_data; + tl_data = tl_data->tl_data_next; + } + } + + return (0); +} + +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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + 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; +} + +krb5_error_code +krb5_dbekd_decrypt_key_data( krb5_context kcontext, + const krb5_keyblock * mkey, + const krb5_key_data * key_data, + krb5_keyblock * dbkey, + krb5_keysalt * keysalt) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + status = + dal_handle->lib_handle->vftabl.dbekd_decrypt_key_data(kcontext, + mkey, key_data, dbkey, keysalt); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + clean_n_exit: + return status; +} + +krb5_error_code +krb5_dbekd_encrypt_key_data( krb5_context kcontext, + const krb5_keyblock * mkey, + const krb5_keyblock * dbkey, + const krb5_keysalt * keysalt, + int keyver, + krb5_key_data * key_data) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + status = + dal_handle->lib_handle->vftabl.dbekd_encrypt_key_data(kcontext, + mkey, dbkey, keysalt, keyver, key_data); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + clean_n_exit: + return status; +} + +krb5_error_code +krb5_db_get_context(krb5_context context, void **db_context) +{ + *db_context = KRB5_DB_GET_DB_CONTEXT(context); + if (*db_context == NULL) { + return KRB5_KDB_DBNOTINITED; + } + + return 0; +} + +krb5_error_code +krb5_db_set_context(krb5_context context, void *db_context) +{ + KRB5_DB_GET_DB_CONTEXT(context) = db_context; + + return 0; +} + +krb5_error_code +krb5_db_invoke(krb5_context kcontext, + unsigned int method, + const krb5_data *req, + krb5_data *rep) +{ + krb5_error_code status = 0; + kdb5_dal_handle *dal_handle; + + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) { + goto clean_n_exit; + } + } + + dal_handle = kcontext->dal_handle; + if (dal_handle->lib_handle->vftabl.db_invoke == NULL) { + status = KRB5_KDB_DBTYPE_NOSUP; + goto clean_n_exit; + } + + status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); + if (status) { + goto clean_n_exit; + } + + status = + dal_handle->lib_handle->vftabl.db_invoke(kcontext, + method, + req, + rep); + kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); + + clean_n_exit: + return status; +} + diff --git a/krb5-1-7/src/lib/kdb/kdb5.h b/krb5-1-7/src/lib/kdb/kdb5.h new file mode 100644 index 000000000..e3a1f2633 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb5.h @@ -0,0 +1,36 @@ +#ifndef _KRB5_KDB5_H_ +#define _KRB5_KDB5_H_ + +#if HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include "kdb.h" +#include "kdb_ext.h" + +#define KRB5_DB_GET_DB_CONTEXT(kcontext) (((kdb5_dal_handle*) (kcontext)->dal_handle)->db_context) +#define KRB5_DB_GET_PROFILE(kcontext) ((kcontext)->profile) +#define KRB5_DB_GET_REALM(kcontext) ((kcontext)->default_realm) + +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; + +struct _kdb5_dal_handle +{ + /* Helps us to change db_library without affecting modules to some + extent. */ + void *db_context; + db_library lib_handle; +}; +/* typedef kdb5_dal_handle is in k5-int.h now */ + +#endif /* end of _KRB5_KDB5_H_ */ diff --git a/krb5-1-7/src/lib/kdb/kdb5int.h b/krb5-1-7/src/lib/kdb/kdb5int.h new file mode 100644 index 000000000..40f38ad21 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb5int.h @@ -0,0 +1,44 @@ +/* + * lib/kdb5/kdb5int.h + * + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 header file for the kdb5 library for internal functions + */ + +#ifndef __KDB5INT_H__ +#define __KDB5INT_H__ + +#include "kdb5.h" + +krb5_error_code +krb5int_put_principal_no_log(krb5_context kcontext, + krb5_db_entry *entries, int *nentries); + +krb5_error_code +krb5int_delete_principal_no_log(krb5_context kcontext, + krb5_principal search_for, + int *nentries); + +#endif /* __KDB5INT_H__ */ diff --git a/krb5-1-7/src/lib/kdb/kdb_convert.c b/krb5-1-7/src/lib/kdb/kdb_convert.c new file mode 100644 index 000000000..cecf5133f --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb_convert.c @@ -0,0 +1,1006 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)kdb_convert.c 1.3 05/01/05 SMI" */ + +/* + * This file contains api's for conversion of the kdb_incr_update_t + * struct(s) into krb5_db_entry struct(s) and vice-versa. + */ +#include +#include +#include +#include +#include +#include "iprop.h" +#include +#include +#include + +/* BEGIN CSTYLED */ +#define ULOG_ENTRY_TYPE(upd, i) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i] + +#define ULOG_ENTRY(upd, i) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u + +#define ULOG_ENTRY_KEYVAL(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_keydata.av_keydata_val[j] + +#define ULOG_ENTRY_PRINC(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_princ.k_components.k_components_val[j] + +#define ULOG_ENTRY_MOD_PRINC(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_mod_princ.k_components.k_components_val[j] +/* END CSTYLED */ + +typedef enum { + REG_PRINC = 0, + MOD_PRINC = 1 +} princ_type; + + +/* + * This routine tracks the krb5_db_entry fields that have been modified + * (by comparing it to the db_entry currently present in principal.db) + * in the update. + */ +static void +find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new, + kdbe_attr_type_t *attrs, int *nattrs) +{ + int i = 0, j = 0; + + krb5_tl_data *first, *second; + + if (current->attributes != new->attributes) + attrs[i++] = AT_ATTRFLAGS; + + if (current->max_life != new->max_life) + attrs[i++] = AT_MAX_LIFE; + + if (current->max_renewable_life != new->max_renewable_life) + attrs[i++] = AT_MAX_RENEW_LIFE; + + if (current->expiration != new->expiration) + attrs[i++] = AT_EXP; + + if (current->pw_expiration != new->pw_expiration) + attrs[i++] = AT_PW_EXP; + + if (current->last_success != new->last_success) + attrs[i++] = AT_LAST_SUCCESS; + + if (current->last_failed != new->last_failed) + attrs[i++] = AT_LAST_FAILED; + + if (current->fail_auth_count != new->fail_auth_count) + attrs[i++] = AT_FAIL_AUTH_COUNT; + + if ((current->princ->type == new->princ->type) && + (current->princ->length == new->princ->length)) { + if ((current->princ->realm.length == + new->princ->realm.length) && + strncmp(current->princ->realm.data, + new->princ->realm.data, + current->princ->realm.length)) { + for (j = 0; j < current->princ->length; j++) { + if ((current->princ->data[j].data != NULL) && + (strncmp(current->princ->data[j].data, + new->princ->data[j].data, + current->princ->data[j].length))) { + attrs[i++] = AT_PRINC; + break; + } + } + } else { + attrs[i++] = AT_PRINC; + } + } else { + attrs[i++] = AT_PRINC; + } + + if (current->n_key_data == new->n_key_data) { + /* Assuming key ordering is the same in new & current */ + for (j = 0; j < new->n_key_data; j++) { + if (current->key_data[j].key_data_kvno != + new->key_data[j].key_data_kvno) { + attrs[i++] = AT_KEYDATA; + break; + } + } + } else { + attrs[i++] = AT_KEYDATA; + } + + if (current->n_tl_data == new->n_tl_data) { + /* Assuming we preserve the TL_DATA ordering between updates */ + for (first = current->tl_data, second = new->tl_data; + first; first = first->tl_data_next, + second = second->tl_data_next) { + if ((first->tl_data_length == second->tl_data_length) && + (first->tl_data_type == second->tl_data_type)) { + if ((memcmp((char *)first->tl_data_contents, + (char *)second->tl_data_contents, + first->tl_data_length)) != 0) { + attrs[i++] = AT_TL_DATA; + break; + } + } else { + attrs[i++] = AT_TL_DATA; + break; + } + } + + } else { + attrs[i++] = AT_TL_DATA; + } + + if (current->len != new->len) + attrs[i++] = AT_LEN; + /* + * Store the no. of (possibly :)) changed attributes + */ + *nattrs = i; +} + + +/* + */ +static int +data_to_utf8str(utf8str_t *u, krb5_data d) +{ + u->utf8str_t_len = d.length; + if (d.data) { + u->utf8str_t_val = malloc(d.length); + if (u->utf8str_t_val == NULL) + return -1; + memcpy(u->utf8str_t_val, d.data, d.length); + } else + u->utf8str_t_val = NULL; + return 0; +} + +/* + * Converts the krb5_principal struct from db2 to ulog format. + */ +static krb5_error_code +conv_princ_2ulog(krb5_principal princ, kdb_incr_update_t *upd, + int cnt, princ_type tp) +{ + int i = 0; + kdbe_princ_t *p; + kdbe_data_t *components; + + if ((upd == NULL) || !princ) + return (KRB5KRB_ERR_GENERIC); + + switch (tp) { + case REG_PRINC: + case MOD_PRINC: + p = &ULOG_ENTRY(upd, cnt).av_princ; /* or av_mod_princ */ + p->k_nametype = (int32_t)princ->type; + + if (data_to_utf8str(&p->k_realm, princ->realm) < 0) { + return ENOMEM; + } + + p->k_components.k_components_len = princ->length; + + p->k_components.k_components_val = components + = malloc(princ->length * sizeof (kdbe_data_t)); + if (p->k_components.k_components_val == NULL) { + free(p->k_realm.utf8str_t_val); + p->k_realm.utf8str_t_val = NULL; + return (ENOMEM); + } + + memset(components, 0, princ->length * sizeof(kdbe_data_t)); + for (i = 0; i < princ->length; i++) + components[i].k_data.utf8str_t_val = NULL; + for (i = 0; i < princ->length; i++) { + components[i].k_magic = princ->data[i].magic; + if (data_to_utf8str(&components[i].k_data, princ->data[i]) < 0) { + int j; + for (j = 0; j < i; j++) { + free(components[j].k_data.utf8str_t_val); + components[j].k_data.utf8str_t_val = NULL; + } + free(components); + p->k_components.k_components_val = NULL; + free(p->k_realm.utf8str_t_val); + p->k_realm.utf8str_t_val = NULL; + return ENOMEM; + } + } + break; + + default: + break; + } + return (0); +} + +/* + * Copies a UTF-8 string from ulog to a krb5_data object, which may + * already have allocated storage associated with it. + * + * Maybe a return value should indicate success/failure? + */ +static void +set_from_utf8str(krb5_data *d, utf8str_t u) +{ + if (u.utf8str_t_len > INT_MAX-1 || u.utf8str_t_len >= SIZE_MAX-1) { + d->data = NULL; + return; + } + d->length = u.utf8str_t_len; + d->data = malloc(d->length + 1); + if (d->data == NULL) + return; + if (d->length) /* Pointer may be null if length = 0. */ + strncpy(d->data, u.utf8str_t_val, d->length); + d->data[d->length] = 0; +} + +/* + * Converts the krb5_principal struct from ulog to db2 format. + */ +static krb5_principal +conv_princ_2db(krb5_context context, kdbe_princ_t *kdbe_princ) +{ + int i; + krb5_principal princ; + kdbe_data_t *components; + + princ = calloc(1, sizeof (krb5_principal_data)); + if (princ == NULL) { + return NULL; + } + princ->length = 0; + princ->data = NULL; + + components = kdbe_princ->k_components.k_components_val; + + princ->type = (krb5_int32) kdbe_princ->k_nametype; + princ->realm.data = NULL; + set_from_utf8str(&princ->realm, kdbe_princ->k_realm); + if (princ->realm.data == NULL) + goto error; + + princ->data = calloc(kdbe_princ->k_components.k_components_len, + sizeof (krb5_data)); + if (princ->data == NULL) + goto error; + for (i = 0; i < kdbe_princ->k_components.k_components_len; i++) + princ->data[i].data = NULL; + princ->length = (krb5_int32)kdbe_princ->k_components.k_components_len; + + for (i = 0; i < princ->length; i++) { + princ->data[i].magic = components[i].k_magic; + set_from_utf8str(&princ->data[i], components[i].k_data); + if (princ->data[i].data == NULL) + goto error; + } + + return princ; +error: + krb5_free_principal(context, princ); + return NULL; +} + + +/* + * This routine converts one or more krb5 db2 records into update + * log (ulog) entry format. Space for the update log entries should + * be allocated prior to invocation of this routine. + */ +krb5_error_code +ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries, + kdb_incr_update_t *updates, + int nentries) +{ + int i, j, k, cnt, final, nattrs, tmpint, nprincs; + unsigned int more; + krb5_principal tmpprinc; + krb5_tl_data *newtl; + krb5_db_entry curr; + krb5_error_code ret; + kdbe_attr_type_t *attr_types; + kdb_incr_update_t *upd; + krb5_db_entry *ent; + int kadm_data_yes; + + if ((updates == NULL) || (entries == NULL)) + return (KRB5KRB_ERR_GENERIC); + + upd = updates; + ent = entries; + + for (k = 0; k < nentries; k++) { + nprincs = nattrs = tmpint = 0; + final = -1; + kadm_data_yes = 0; + attr_types = NULL; + + if ((upd->kdb_update.kdbe_t_val = (kdbe_val_t *) + malloc(MAXENTRY_SIZE)) == NULL) { + return (ENOMEM); + } + + /* + * Find out which attrs have been modified + */ + if ((attr_types = (kdbe_attr_type_t *)malloc( + sizeof (kdbe_attr_type_t) * MAXATTRS_SIZE)) + == NULL) { + return (ENOMEM); + } + + if ((ret = krb5_db_get_principal(context, ent->princ, &curr, + &nprincs, &more))) { + free(attr_types); + return (ret); + } + + if (nprincs == 0) { + /* + * This is a new entry to the database, hence will + * include all the attribute-value pairs + * + * We leave out the TL_DATA types which we model as + * attrs in kdbe_attr_type_t, since listing AT_TL_DATA + * encompasses these other types-turned-attributes + * + * So, we do *NOT* consider AT_MOD_PRINC, AT_MOD_TIME, + * AT_MOD_WHERE, AT_PW_LAST_CHANGE, AT_PW_POLICY, + * AT_PW_POLICY_SWITCH, AT_PW_HIST_KVNO and AT_PW_HIST, + * totalling 8 attrs. + */ + while (nattrs < MAXATTRS_SIZE - 8) { + attr_types[nattrs] = nattrs; + nattrs++; + } + } else { + find_changed_attrs(&curr, ent, attr_types, &nattrs); + + krb5_db_free_principal(context, &curr, nprincs); + } + + for (i = 0; i < nattrs; i++) { + switch (attr_types[i]) { + case AT_ATTRFLAGS: + if (ent->attributes >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_ATTRFLAGS; + ULOG_ENTRY(upd, final).av_attrflags = + (uint32_t)ent->attributes; + } + break; + + case AT_MAX_LIFE: + if (ent->max_life >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_MAX_LIFE; + ULOG_ENTRY(upd, final).av_max_life = + (uint32_t)ent->max_life; + } + break; + + case AT_MAX_RENEW_LIFE: + if (ent->max_renewable_life >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_MAX_RENEW_LIFE; + ULOG_ENTRY(upd, + final).av_max_renew_life = + (uint32_t)ent->max_renewable_life; + } + break; + + case AT_EXP: + if (ent->expiration >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_EXP; + ULOG_ENTRY(upd, final).av_exp = + (uint32_t)ent->expiration; + } + break; + + case AT_PW_EXP: + if (ent->pw_expiration >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_PW_EXP; + ULOG_ENTRY(upd, final).av_pw_exp = + (uint32_t)ent->pw_expiration; + } + break; + + case AT_LAST_SUCCESS: + if (ent->last_success >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_LAST_SUCCESS; + ULOG_ENTRY(upd, + final).av_last_success = + (uint32_t)ent->last_success; + } + break; + + case AT_LAST_FAILED: + if (ent->last_failed >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_LAST_FAILED; + ULOG_ENTRY(upd, + final).av_last_failed = + (uint32_t)ent->last_failed; + } + break; + + case AT_FAIL_AUTH_COUNT: + if (ent->fail_auth_count >= (krb5_kvno)0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_FAIL_AUTH_COUNT; + ULOG_ENTRY(upd, + final).av_fail_auth_count = + (uint32_t)ent->fail_auth_count; + } + break; + + case AT_PRINC: + if (ent->princ->length > 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_PRINC; + if ((ret = conv_princ_2ulog(ent->princ, + upd, final, REG_PRINC))) { + free(attr_types); + return (ret); + } + } + break; + + case AT_KEYDATA: +/* BEGIN CSTYLED */ + if (ent->n_key_data >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_KEYDATA; + ULOG_ENTRY(upd, final).av_keydata.av_keydata_len = ent->n_key_data; + + ULOG_ENTRY(upd, final).av_keydata.av_keydata_val = malloc(ent->n_key_data * sizeof (kdbe_key_t)); + if (ULOG_ENTRY(upd, final).av_keydata.av_keydata_val == NULL) { + free(attr_types); + return (ENOMEM); + } + + for (j = 0; j < ent->n_key_data; j++) { + ULOG_ENTRY_KEYVAL(upd, final, j).k_ver = ent->key_data[j].key_data_ver; + ULOG_ENTRY_KEYVAL(upd, final, j).k_kvno = ent->key_data[j].key_data_kvno; + ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_len = ent->key_data[j].key_data_ver; + ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_len = ent->key_data[j].key_data_ver; + + ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val = malloc(ent->key_data[j].key_data_ver * sizeof(int32_t)); + if (ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val == NULL) { + free(attr_types); + return (ENOMEM); + } + + ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val = malloc(ent->key_data[j].key_data_ver * sizeof(utf8str_t)); + if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val == NULL) { + free(attr_types); + return (ENOMEM); + } + + for (cnt = 0; cnt < ent->key_data[j].key_data_ver; cnt++) { + ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val[cnt] = ent->key_data[j].key_data_type[cnt]; + ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_len = ent->key_data[j].key_data_length[cnt]; + ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val = malloc(ent->key_data[j].key_data_length[cnt] * sizeof (char)); + if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val == NULL) { + free(attr_types); + return (ENOMEM); + } + (void) memcpy(ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val, ent->key_data[j].key_data_contents[cnt], ent->key_data[j].key_data_length[cnt]); + } + } + } + break; + + case AT_TL_DATA: + ret = krb5_dbe_lookup_last_pwd_change(context, + ent, &tmpint); + if (ret == 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_PW_LAST_CHANGE; + ULOG_ENTRY(upd, final).av_pw_last_change = tmpint; + } + tmpint = 0; + + if(!(ret = krb5_dbe_lookup_mod_princ_data( + context, ent, &tmpint, &tmpprinc))) { + + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_MOD_PRINC; + + ret = conv_princ_2ulog(tmpprinc, + upd, final, MOD_PRINC); + krb5_free_principal(context, tmpprinc); + if (ret) { + free(attr_types); + return (ret); + } + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_MOD_TIME; + ULOG_ENTRY(upd, final).av_mod_time = + tmpint; + } + + newtl = ent->tl_data; + while (newtl) { + switch (newtl->tl_data_type) { + case KRB5_TL_LAST_PWD_CHANGE: + case KRB5_TL_MOD_PRINC: + break; + + case KRB5_TL_KADM_DATA: + default: + if (kadm_data_yes == 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = AT_TL_DATA; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_len = 0; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_val = malloc(ent->n_tl_data * sizeof(kdbe_tl_t)); + + if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val == NULL) { + free(attr_types); + return (ENOMEM); + } + kadm_data_yes = 1; + } + + tmpint = ULOG_ENTRY(upd, final).av_tldata.av_tldata_len; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_len++; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_type = newtl->tl_data_type; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_len = newtl->tl_data_length; + ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val = malloc(newtl->tl_data_length * sizeof (char)); + if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val == NULL) { + free(attr_types); + return (ENOMEM); + } + (void) memcpy(ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val, newtl->tl_data_contents, newtl->tl_data_length); + break; + } + newtl = newtl->tl_data_next; + } + break; +/* END CSTYLED */ + + case AT_LEN: + if (ent->len >= 0) { + ULOG_ENTRY_TYPE(upd, ++final).av_type = + AT_LEN; + ULOG_ENTRY(upd, final).av_len = + (int16_t)ent->len; + } + break; + + default: + break; + } + + } + + free(attr_types); + + /* + * Update len field in kdb_update + */ + upd->kdb_update.kdbe_t_len = ++final; + + /* + * Bump up to next struct + */ + upd++; + ent++; + } + return (0); +} + +/* + * This routine converts one or more update log (ulog) entries into + * kerberos db2 records. Required memory should be allocated + * for the db2 records (pointed to by krb5_db_entry *ent), prior + * to calling this routine. + */ +krb5_error_code +ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries, + kdb_incr_update_t *updates, + int nentries) +{ + int k; + krb5_db_entry *ent; + kdb_incr_update_t *upd; + + if ((updates == NULL) || (entries == NULL)) + return (KRB5KRB_ERR_GENERIC); + + ent = entries; + upd = updates; + + for (k = 0; k < nentries; k++) { + krb5_principal mod_princ = NULL; + int i, j, cnt = 0, mod_time = 0, nattrs, nprincs = 0; + krb5_principal dbprinc; + char *dbprincstr = NULL; + + krb5_tl_data *newtl = NULL; + krb5_error_code ret; + unsigned int more; + unsigned int prev_n_keys = 0; + + /* + * If the ulog entry represents a DELETE update, + * just skip to the next entry. + */ + if (upd->kdb_deleted == TRUE) + goto next; + + /* + * Store the no. of changed attributes in nattrs + */ + nattrs = upd->kdb_update.kdbe_t_len; + + dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len + 1) + * sizeof (char)); + if (dbprincstr == NULL) + return (ENOMEM); + strncpy(dbprincstr, (char *)upd->kdb_princ_name.utf8str_t_val, + upd->kdb_princ_name.utf8str_t_len); + dbprincstr[upd->kdb_princ_name.utf8str_t_len] = 0; + + ret = krb5_parse_name(context, dbprincstr, &dbprinc); + free(dbprincstr); + if (ret) + return (ret); + + ret = krb5_db_get_principal(context, dbprinc, ent, &nprincs, + &more); + krb5_free_principal(context, dbprinc); + if (ret) + return (ret); + + /* + * Set ent->n_tl_data = 0 initially, if this is an ADD update + */ + if (nprincs == 0) + ent->n_tl_data = 0; + + for (i = 0; i < nattrs; i++) { + krb5_principal tmpprinc = NULL; + +#define u (ULOG_ENTRY(upd, i)) + switch (ULOG_ENTRY_TYPE(upd, i).av_type) { + case AT_ATTRFLAGS: + ent->attributes = (krb5_flags) u.av_attrflags; + break; + + case AT_MAX_LIFE: + ent->max_life = (krb5_deltat) u.av_max_life; + break; + + case AT_MAX_RENEW_LIFE: + ent->max_renewable_life = (krb5_deltat) u.av_max_renew_life; + break; + + case AT_EXP: + ent->expiration = (krb5_timestamp) u.av_exp; + break; + + case AT_PW_EXP: + ent->pw_expiration = (krb5_timestamp) u.av_pw_exp; + break; + + case AT_LAST_SUCCESS: + ent->last_success = (krb5_timestamp) u.av_last_success; + break; + + case AT_LAST_FAILED: + ent->last_failed = (krb5_timestamp) u.av_last_failed; + break; + + case AT_FAIL_AUTH_COUNT: + ent->fail_auth_count = (krb5_kvno) u.av_fail_auth_count; + break; + + case AT_PRINC: + tmpprinc = conv_princ_2db(context, &u.av_princ); + if (tmpprinc == NULL) + return ENOMEM; + if (nprincs) + krb5_free_principal(context, ent->princ); + ent->princ = tmpprinc; + break; + + case AT_KEYDATA: + if (nprincs != 0) + prev_n_keys = ent->n_key_data; + else + prev_n_keys = 0; + ent->n_key_data = (krb5_int16)u.av_keydata.av_keydata_len; + if (nprincs == 0) + ent->key_data = NULL; + + ent->key_data = (krb5_key_data *)realloc(ent->key_data, + (ent->n_key_data * + sizeof (krb5_key_data))); + /* XXX Memory leak: Old key data in + records eliminated by resizing to + smaller size. */ + if (ent->key_data == NULL) + /* XXX Memory leak: old storage. */ + return (ENOMEM); + +/* BEGIN CSTYLED */ + for (j = prev_n_keys; j < ent->n_key_data; j++) { + for (cnt = 0; cnt < 2; cnt++) { + ent->key_data[j].key_data_contents[cnt] = NULL; + } + } + for (j = 0; j < ent->n_key_data; j++) { + krb5_key_data *kp = &ent->key_data[j]; + kdbe_key_t *kv = &ULOG_ENTRY_KEYVAL(upd, i, j); + kp->key_data_ver = (krb5_int16)kv->k_ver; + kp->key_data_kvno = (krb5_int16)kv->k_kvno; + if (kp->key_data_ver > 2) { + return EINVAL; /* XXX ? */ + } + + for (cnt = 0; cnt < kp->key_data_ver; cnt++) { + void *newptr; + kp->key_data_type[cnt] = (krb5_int16)kv->k_enctype.k_enctype_val[cnt]; + kp->key_data_length[cnt] = (krb5_int16)kv->k_contents.k_contents_val[cnt].utf8str_t_len; + newptr = realloc(kp->key_data_contents[cnt], + kp->key_data_length[cnt]); + if (newptr == NULL) + return ENOMEM; + kp->key_data_contents[cnt] = newptr; + + (void) memset(kp->key_data_contents[cnt], 0, + kp->key_data_length[cnt]); + (void) memcpy(kp->key_data_contents[cnt], + kv->k_contents.k_contents_val[cnt].utf8str_t_val, + kp->key_data_length[cnt]); + } + } + break; + + case AT_TL_DATA: + cnt = u.av_tldata.av_tldata_len; + newtl = malloc(cnt * sizeof (krb5_tl_data)); + (void) memset(newtl, 0, (cnt * sizeof (krb5_tl_data))); + if (newtl == NULL) + return (ENOMEM); + + for (j = 0; j < cnt; j++) { + newtl[j].tl_data_type = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_type; + newtl[j].tl_data_length = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_data.tl_data_len; + newtl[j].tl_data_contents = NULL; + newtl[j].tl_data_contents = malloc(newtl[j].tl_data_length * sizeof (krb5_octet)); + if (newtl[j].tl_data_contents == NULL) + /* XXX Memory leak: newtl + and previously + allocated elements. */ + return (ENOMEM); + + (void) memset(newtl[j].tl_data_contents, 0, (newtl[j].tl_data_length * sizeof (krb5_octet))); + (void) memcpy(newtl[j].tl_data_contents, u.av_tldata.av_tldata_val[j].tl_data.tl_data_val, newtl[j].tl_data_length); + newtl[j].tl_data_next = NULL; + if (j > 0) + newtl[j - 1].tl_data_next = &newtl[j]; + } + + if ((ret = krb5_dbe_update_tl_data(context, ent, newtl))) + return (ret); + for (j = 0; j < cnt; j++) + if (newtl[j].tl_data_contents) { + free(newtl[j].tl_data_contents); + newtl[j].tl_data_contents = NULL; + } + if (newtl) { + free(newtl); + newtl = NULL; + } + break; +/* END CSTYLED */ + + case AT_PW_LAST_CHANGE: + if ((ret = krb5_dbe_update_last_pwd_change(context, ent, + u.av_pw_last_change))) + return (ret); + break; + + case AT_MOD_PRINC: + tmpprinc = conv_princ_2db(context, &u.av_mod_princ); + if (tmpprinc == NULL) + return ENOMEM; + mod_princ = tmpprinc; + break; + + case AT_MOD_TIME: + mod_time = u.av_mod_time; + break; + + case AT_LEN: + ent->len = (krb5_int16) u.av_len; + break; + + default: + break; + } +#undef u + } + + /* + * process mod_princ_data request + */ + if (mod_time && mod_princ) { + ret = krb5_dbe_update_mod_princ_data(context, ent, + mod_time, mod_princ); + krb5_free_principal(context, mod_princ); + mod_princ = NULL; + if (ret) + return (ret); + } + + next: + /* + * Bump up to next struct + */ + upd++; + ent++; + } + return (0); +} + + + +/* + * This routine frees up memory associated with the bunched ulog entries. + */ +void +ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates) +{ + + kdb_incr_update_t *upd; + int i, j, k, cnt; + + if (updates == NULL) + return; + + upd = updates; + + /* + * Loop thru each ulog entry + */ + for (cnt = 0; cnt < no_of_updates; cnt++) { + + /* + * ulog entry - kdb_princ_name + */ + free(upd->kdb_princ_name.utf8str_t_val); + +/* BEGIN CSTYLED */ + + /* + * ulog entry - kdb_kdcs_seen_by + */ + if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) { + for (i = 0; i < upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len; i++) + free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val); + free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val); + } + + /* + * ulog entry - kdb_futures + */ + free(upd->kdb_futures.kdb_futures_val); + + /* + * ulog entry - kdb_update + */ + if (upd->kdb_update.kdbe_t_val) { + /* + * Loop thru all the attributes and free up stuff + */ + for (i = 0; i < upd->kdb_update.kdbe_t_len; i++) { + + /* + * Free av_key_data + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_KEYDATA) && ULOG_ENTRY(upd, i).av_keydata.av_keydata_val) { + + for (j = 0; j < ULOG_ENTRY(upd, i).av_keydata.av_keydata_len; j++) { + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val); + if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val) { + for (k = 0; k < ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; k++) { + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val); + } + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val); + } + } + free(ULOG_ENTRY(upd, i).av_keydata.av_keydata_val); + } + + + /* + * Free av_tl_data + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_TL_DATA) && ULOG_ENTRY(upd, i).av_tldata.av_tldata_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; j++) { + free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val); + } + free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val); + } + + /* + * Free av_princ + */ + if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_PRINC) { + free(ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val); + if (ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_princ.k_components.k_components_len; j++) { + free(ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val); + } + free(ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val); + } + } + + /* + * Free av_mod_princ + */ + if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_PRINC) { + free(ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val); + if (ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_len; j++) { + free(ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val); + } + free(ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val); + } + } + + /* + * Free av_mod_where + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_WHERE) && ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val) + free(ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val); + + /* + * Free av_pw_policy + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_POLICY) && ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val) + free(ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val); + + /* + * XXX: Free av_pw_hist + * + * For now, we just free the pointer + * to av_pw_hist_val, since we aren't + * populating this union member in + * the conv api function(s) anyways. + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_HIST) && ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val) + free(ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val); + + } + + /* + * Free up the pointer to kdbe_t_val + */ + free(upd->kdb_update.kdbe_t_val); + } + +/* END CSTYLED */ + + /* + * Bump up to next struct + */ + upd++; + } + + + /* + * Finally, free up the pointer to the bunched ulog entries + */ + free(updates); +} diff --git a/krb5-1-7/src/lib/kdb/kdb_cpw.c b/krb5-1-7/src/lib/kdb/kdb_cpw.c new file mode 100644 index 000000000..55e8199d2 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb_cpw.c @@ -0,0 +1,636 @@ +/* + * lib/kdb/kdb_cpw.c + * + * Copyright 1995, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include + +int +krb5_db_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 = krb5_db_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 = krb5_db_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; + free(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: + /* The afs_mit_string_to_key needs to use strlen, and the + realm field is not (necessarily) NULL terminated. */ + retval = krb5int_copy_data_contents_add0(context, + krb5_princ_realm(context, + db_entry->princ), + &key_salt.data); + if (retval) + return retval; + key_salt.data.length = SALT_TYPE_AFS_LENGTH; /*length actually used below...*/ + 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); + free(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 = krb5_db_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 = krb5_db_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-7/src/lib/kdb/kdb_default.c b/krb5-1-7/src/lib/kdb/kdb_default.c new file mode 100644 index 000000000..b2f471b4d --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb_default.c @@ -0,0 +1,680 @@ +/* + * lib/kdb/kdb_helper.c + * + * Copyright 1995, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "k5-int.h" +#include "kdb.h" +#include +#include +#include +#include + + +/* + * 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_list(krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd) +{ + krb5_error_code retval = 0; + char defkeyfile[MAXPATHLEN+1]; + char *tmp_ktname = NULL, *tmp_ktpath; + krb5_data *realm = krb5_princ_realm(context, mname); + krb5_keytab kt = NULL; + krb5_keytab_entry new_entry; + struct stat stb; + int statrc; + + if (!keyfile) { + (void) snprintf(defkeyfile, sizeof(defkeyfile), "%s%s", + DEFAULT_KEYFILE_STUB, realm->data); + keyfile = defkeyfile; + } + + /* + * XXX making the assumption that the keyfile is in a dir that requires root + * privilege to write to thus making timing attacks unlikely. + */ + if ((statrc = stat(keyfile, &stb)) >= 0) { + /* if keyfile exists it better be a regular file */ + if (!S_ISREG(stb.st_mode)) { + retval = EINVAL; + krb5_set_error_message (context, retval, + "keyfile (%s) is not a regular file: %s", + keyfile, error_message(retval)); + goto out; + } + } + + /* Use temp keytab file name in case creation of keytab fails */ + + /* create temp file template for use by mktemp() */ + if ((retval = asprintf(&tmp_ktname, "WRFILE:%s_XXXXXX", keyfile)) < 0) { + krb5_set_error_message (context, retval, + "Could not create temp keytab file name."); + goto out; + } + + /* + * Set tmp_ktpath to point to the keyfile path (skip WRFILE:). Subtracting + * 1 to account for NULL terminator in sizeof calculation of a string + * constant. Used further down. + */ + tmp_ktpath = tmp_ktname + (sizeof("WRFILE:") - 1); + + if (mktemp(tmp_ktpath) == NULL) { + retval = errno; + krb5_set_error_message (context, retval, + "Could not create temp stash file: %s", + error_message(errno)); + goto out; + } + + /* create new stash keytab using temp file name */ + retval = krb5_kt_resolve(context, tmp_ktname, &kt); + if (retval != 0) + goto out; + + while (keylist && !retval) { + memset((char *) &new_entry, 0, sizeof(new_entry)); + new_entry.principal = mname; + new_entry.key = keylist->keyblock; + new_entry.vno = keylist->kvno; + + retval = krb5_kt_add_entry(context, kt, &new_entry); + keylist = keylist->next; + } + krb5_kt_close(context, kt); + + if (retval != 0) { + /* delete tmp keyfile if it exists and an error occurrs */ + if (stat(keyfile, &stb) >= 0) + (void) unlink(tmp_ktpath); + } else { + /* rename original keyfile to original filename */ + if (rename(tmp_ktpath, keyfile) < 0) { + retval = errno; + krb5_set_error_message (context, retval, + "rename of temporary keyfile (%s) to (%s) failed: %s", + tmp_ktpath, keyfile, error_message(errno)); + } + } + +out: + if (tmp_ktname != NULL) + free(tmp_ktname); + + return retval; +} + +krb5_error_code +krb5_def_store_mkey(krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_kvno kvno, + krb5_keyblock *key, + char *master_pwd) +{ + krb5_keylist_node list; + + list.kvno = kvno; + list.keyblock = *key; + list.next = NULL; + return krb5_def_store_mkey_list(context, keyfile, mname, &list, + master_pwd); +} + +static krb5_error_code +krb5_db_def_fetch_mkey_stash(krb5_context context, + const char *keyfile, + krb5_keyblock *key, + krb5_kvno *kvno) +{ + krb5_error_code retval = 0; + krb5_ui_2 enctype; + krb5_ui_4 keylength; + FILE *kf = NULL; + +#ifdef ANSI_STDIO + if (!(kf = fopen(keyfile, "rb"))) +#else + if (!(kf = fopen(keyfile, "r"))) +#endif + return KRB5_KDB_CANTREAD_STORED; + set_cloexec_file(kf); + + if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) { + retval = KRB5_KDB_CANTREAD_STORED; + goto errout; + } + +#if BIG_ENDIAN_MASTER_KEY + enctype = ntohs((uint16_t) enctype); +#endif + + if (key->enctype == ENCTYPE_UNKNOWN) + key->enctype = enctype; + else if (enctype != key->enctype) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + + if (fread((krb5_pointer) &keylength, + sizeof(keylength), 1, kf) != 1) { + retval = KRB5_KDB_CANTREAD_STORED; + goto errout; + } + +#if BIG_ENDIAN_MASTER_KEY + key->length = ntohl((uint32_t) keylength); +#else + key->length = keylength; +#endif + + 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; + zap(key->contents, key->length); + free(key->contents); + key->contents = 0; + } else + retval = 0; + + /* + * Note, the old stash format did not store the kvno and at this point it + * can be assumed to be 1 as is the case for the mkey princ. If the kvno is + * passed in and isn't ignore_vno just leave it alone as this could cause + * verifcation trouble if the mkey princ is using a kvno other than 1. + */ + if (kvno && *kvno == IGNORE_VNO) + *kvno = 1; + + errout: + (void) fclose(kf); + return retval; +} + +static krb5_error_code +krb5_db_def_fetch_mkey_keytab(krb5_context context, + const char *keyfile, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno) +{ + krb5_error_code retval = 0; + krb5_keytab kt = NULL; + krb5_keytab_entry kt_ent; + krb5_enctype enctype = IGNORE_ENCTYPE; + + if ((retval = krb5_kt_resolve(context, keyfile, &kt)) != 0) + goto errout; + + /* override default */ + if (key->enctype != ENCTYPE_UNKNOWN) + enctype = key->enctype; + + if ((retval = krb5_kt_get_entry(context, kt, mname, + kvno ? *kvno : IGNORE_VNO, + enctype, + &kt_ent)) == 0) { + + if (key->enctype == ENCTYPE_UNKNOWN) + key->enctype = kt_ent.key.enctype; + + if (((int) kt_ent.key.length) < 0) { + retval = KRB5_KDB_BADSTORED_MKEY; + krb5_kt_free_entry(context, &kt_ent); + goto errout; + } + + key->length = kt_ent.key.length; + + /* + * If a kvno pointer was passed in and it dereferences the + * IGNORE_VNO value then it should be assigned the value of the kvno + * found in the keytab otherwise the KNVO specified should be the + * same as the one returned from the keytab. + */ + if (kvno != NULL && *kvno == IGNORE_VNO) + *kvno = kt_ent.vno; + + /* + * kt_ent will be free'd so need to allocate and copy key contents for + * output to caller. + */ + if (!(key->contents = (krb5_octet *)malloc(key->length))) { + retval = ENOMEM; + krb5_kt_free_entry(context, &kt_ent); + goto errout; + } + memcpy(key->contents, kt_ent.key.contents, kt_ent.key.length); + krb5_kt_free_entry(context, &kt_ent); + } + +errout: + if (kt) + krb5_kt_close(context, kt); + + return retval; +} + +krb5_error_code +krb5_db_def_fetch_mkey(krb5_context context, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args) +{ + krb5_error_code retval; + char keyfile[MAXPATHLEN+1]; + krb5_data *realm = krb5_princ_realm(context, mname); + + key->magic = KV5M_KEYBLOCK; + + if (db_args != NULL) { + (void) strncpy(keyfile, db_args, sizeof(keyfile)); + } else { + (void) snprintf(keyfile, sizeof(keyfile), "%s%s", + DEFAULT_KEYFILE_STUB, realm->data); + } + /* null terminate no matter what */ + keyfile[sizeof(keyfile) - 1] = '\0'; + + /* Try the keytab and old stash file formats. */ + retval = krb5_db_def_fetch_mkey_keytab(context, keyfile, mname, key, kvno); + if (retval == KRB5_KEYTAB_BADVNO) + retval = krb5_db_def_fetch_mkey_stash(context, keyfile, key, kvno); + + /* + * Use a generic error code for failure to retrieve the master + * key, but set a message indicating the actual error. + */ + if (retval != 0) { + krb5_set_error_message(context, KRB5_KDB_CANTREAD_STORED, + "Can not fetch master key (error: %s).", + error_message(retval)); + return KRB5_KDB_CANTREAD_STORED; + } else + return 0; +} + +/* + * Note, this verifies that the input mkey is currently protecting all the mkeys + */ +krb5_error_code +krb5_def_verify_master_key(krb5_context context, + krb5_principal mprinc, + krb5_kvno kvno, + 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; + } + + if (kvno != IGNORE_VNO && + kvno != (krb5_kvno) master_entry.key_data->key_data_kvno) { + retval = KRB5_KDB_BADMASTERKEY; + krb5_set_error_message (context, retval, + "User specified mkeyVNO (%u) does not match master key princ's KVNO (%u)", + kvno, master_entry.key_data->key_data_kvno); + } + + zap((char *)tempkey.contents, tempkey.length); + free(tempkey.contents); + krb5_db_free_principal(context, &master_entry, nprinc); + + return retval; +} + +krb5_error_code +krb5_def_fetch_mkey_list(krb5_context context, + krb5_principal mprinc, + const krb5_keyblock *mkey, + krb5_kvno mkvno, + krb5_keylist_node **mkeys_list) +{ + krb5_error_code retval; + krb5_db_entry master_entry; + int nprinc; + krb5_boolean more, found_key = FALSE; + krb5_keyblock cur_mkey; + krb5_keylist_node *mkey_list_head = NULL, **mkey_list_node; + krb5_key_data *key_data; + krb5_mkey_aux_node *mkey_aux_data_list = NULL, *aux_data_entry; + int i; + + if (mkeys_list == NULL) + return (EINVAL); + + memset(&cur_mkey, 0, sizeof(cur_mkey)); + memset(&master_entry, 0, sizeof(master_entry)); + + 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); + } + + /* + * Check if the input mkey is the latest key and if it isn't then find the + * latest mkey. + */ + + if (mkey->enctype == master_entry.key_data[0].key_data_type[0]) { + if (krb5_dbekd_decrypt_key_data(context, mkey, + &master_entry.key_data[0], + &cur_mkey, NULL) == 0) { + found_key = TRUE; + } + } + + if (!found_key) { + /* + * Note the mkvno may provide a hint as to which mkey_aux tuple to + * decrypt. + */ + if ((retval = krb5_dbe_lookup_mkey_aux(context, &master_entry, + &mkey_aux_data_list))) + goto clean_n_exit; + + /* mkvno may be 0 in some cases like keyboard and should be ignored */ + if (mkvno != 0) { + /* for performance sake, try decrypting with matching kvno */ + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + if (aux_data_entry->mkey_kvno == mkvno) { + if (krb5_dbekd_decrypt_key_data(context, mkey, + &aux_data_entry->latest_mkey, + &cur_mkey, NULL) == 0) { + found_key = TRUE; + break; + } + } + } + } + if (!found_key) { + /* given the importance of acquiring the latest mkey, try brute force */ + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + if (mkey->enctype == aux_data_entry->latest_mkey.key_data_type[0] && + (krb5_dbekd_decrypt_key_data(context, mkey, + &aux_data_entry->latest_mkey, + &cur_mkey, NULL) == 0)) { + found_key = TRUE; + break; + } + } + if (found_key != TRUE) { + krb5_set_error_message (context, KRB5_KDB_BADMASTERKEY, + "Unable to decrypt latest master key with the provided master key\n"); + retval = KRB5_KDB_BADMASTERKEY; + goto clean_n_exit; + } + } + } + + /* + * Extract all the mkeys from master_entry using the most current mkey and + * create a mkey list for the mkeys field in kdc_realm_t. + */ + + mkey_list_head = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node)); + if (mkey_list_head == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + + memset(mkey_list_head, 0, sizeof(krb5_keylist_node)); + + /* Set mkey_list_head to the current mkey as an optimization. */ + /* mkvno may not be latest so ... */ + mkey_list_head->kvno = master_entry.key_data[0].key_data_kvno; + /* this is the latest clear mkey (avoids a redundant decrypt) */ + mkey_list_head->keyblock = cur_mkey; + + /* loop through any other master keys creating a list of krb5_keylist_nodes */ + mkey_list_node = &mkey_list_head->next; + for (i = 1; i < master_entry.n_key_data; i++) { + if (*mkey_list_node == NULL) { + /* *mkey_list_node points to next field of previous node */ + *mkey_list_node = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node)); + if (*mkey_list_node == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(*mkey_list_node, 0, sizeof(krb5_keylist_node)); + } + key_data = &master_entry.key_data[i]; + retval = krb5_dbekd_decrypt_key_data(context, &cur_mkey, + key_data, + &((*mkey_list_node)->keyblock), + NULL); + if (retval) + goto clean_n_exit; + + (*mkey_list_node)->kvno = key_data->key_data_kvno; + mkey_list_node = &((*mkey_list_node)->next); + } + + *mkeys_list = mkey_list_head; + +clean_n_exit: + krb5_db_free_principal(context, &master_entry, nprinc); + krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_list); + if (retval != 0) + krb5_dbe_free_key_list(context, mkey_list_head); + 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 kdb_def_set_mkey_list ( krb5_context kcontext, + krb5_keylist_node *keylist ) +{ + /* printf("default set master key\n"); */ + return 0; +} + +krb5_error_code kdb_def_get_mkey_list ( krb5_context kcontext, + krb5_keylist_node **keylist ) +{ + /* 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-7/src/lib/kdb/kdb_log.c b/krb5-1-7/src/lib/kdb/kdb_log.c new file mode 100644 index 000000000..3652935a1 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/kdb_log.c @@ -0,0 +1,935 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)kdb_log.c 1.3 04/02/23 SMI" */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kdb5.h" +#include "kdb_log.h" +#include "kdb5int.h" + +/* + * This modules includes all the necessary functions that create and + * modify the Kerberos principal update and header logs. + */ + +#define getpagesize() sysconf(_SC_PAGESIZE) + +static int pagesize = 0; + +#define INIT_ULOG(ctx) \ + log_ctx = ctx->kdblog_context; \ + assert(log_ctx != NULL); \ + ulog = log_ctx->ulog; \ + assert(ulog != NULL) + +/* XXX */ +typedef unsigned long ulong_t; +typedef unsigned int uint_t; + +static int extend_file_to(int fd, uint_t new_size); + +krb5_error_code +ulog_lock(krb5_context ctx, int mode) +{ + kdb_log_context *log_ctx = NULL; + kdb_hlog_t *ulog = NULL; + + if (ctx == NULL) + return KRB5_LOG_ERROR; + if (ctx->kdblog_context == NULL || ctx->kdblog_context->iproprole == IPROP_NULL) + return 0; + INIT_ULOG(ctx); + return krb5_lock_file(ctx, log_ctx->ulogfd, mode); +} + +/* + * Sync update entry to disk. + */ +static krb5_error_code +ulog_sync_update(kdb_hlog_t *ulog, kdb_ent_header_t *upd) +{ + ulong_t start, end, size; + krb5_error_code retval; + + if (ulog == NULL) + return (KRB5_LOG_ERROR); + + if (!pagesize) + pagesize = getpagesize(); + + start = ((ulong_t)upd) & (~(pagesize-1)); + + end = (((ulong_t)upd) + ulog->kdb_block + + (pagesize-1)) & (~(pagesize-1)); + + size = end - start; + if ((retval = msync((caddr_t)start, size, MS_SYNC))) { + return (retval); + } + + return (0); +} + +/* + * Sync memory to disk for the update log header. + */ +static void +ulog_sync_header(kdb_hlog_t *ulog) +{ + + if (!pagesize) + pagesize = getpagesize(); + + if (msync((caddr_t)ulog, pagesize, MS_SYNC)) { + /* + * Couldn't sync to disk, let's panic + */ + syslog(LOG_ERR, "ulog_sync_header: could not sync to disk"); + abort(); + } +} + +/* + * Resizes the array elements. We reinitialize the update log rather than + * unrolling the the log and copying it over to a temporary log for obvious + * performance reasons. Slaves will subsequently do a full resync, but + * the need for resizing should be very small. + */ +static krb5_error_code +ulog_resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, uint_t recsize) +{ + uint_t new_block, new_size; + + if (ulog == NULL) + return (KRB5_LOG_ERROR); + + new_size = sizeof (kdb_hlog_t); + + new_block = (recsize / ULOG_BLOCK) + 1; + new_block *= ULOG_BLOCK; + + new_size += ulogentries * new_block; + + if (new_size <= MAXLOGLEN) { + /* + * Reinit log with new block size + */ + (void) memset(ulog, 0, sizeof (kdb_hlog_t)); + + ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + ulog->db_version_num = KDB_VERSION; + ulog->kdb_state = KDB_STABLE; + ulog->kdb_block = new_block; + + ulog_sync_header(ulog); + + /* + * Time to expand log considering new block size + */ + if (extend_file_to(ulogfd, new_size) < 0) + return errno; + } else { + /* + * Can't map into file larger than MAXLOGLEN + */ + return (KRB5_LOG_ERROR); + } + + return (0); +} + +/* + * Adds an entry to the update log. + * The layout of the update log looks like: + * + * header log -> [ update header -> xdr(kdb_incr_update_t) ], ... + */ +krb5_error_code +ulog_add_update(krb5_context context, kdb_incr_update_t *upd) +{ + XDR xdrs; + kdbe_time_t ktime; + struct timeval timestamp; + kdb_ent_header_t *indx_log; + uint_t i, recsize; + ulong_t upd_size; + krb5_error_code retval; + kdb_sno_t cur_sno; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + uint32_t ulogentries; + int ulogfd; + + INIT_ULOG(context); + ulogentries = log_ctx->ulogentries; + ulogfd = log_ctx->ulogfd; + + if (upd == NULL) + return (KRB5_LOG_ERROR); + + (void) gettimeofday(×tamp, NULL); + ktime.seconds = timestamp.tv_sec; + ktime.useconds = timestamp.tv_usec; + + upd_size = xdr_sizeof((xdrproc_t)xdr_kdb_incr_update_t, upd); + + recsize = sizeof (kdb_ent_header_t) + upd_size; + + if (recsize > ulog->kdb_block) { + if ((retval = ulog_resize(ulog, ulogentries, ulogfd, recsize))) { + /* Resize element array failed */ + return (retval); + } + } + + cur_sno = ulog->kdb_last_sno; + + /* + * We need to overflow our sno, replicas will do full + * resyncs once they see their sno > than the masters. + */ + if (cur_sno == ULONG_MAX) + cur_sno = 1; + else + cur_sno++; + + /* + * We squirrel this away for finish_update() to index + */ + upd->kdb_entry_sno = cur_sno; + + i = (cur_sno - 1) % ulogentries; + + indx_log = (kdb_ent_header_t *)INDEX(ulog, i); + + (void) memset(indx_log, 0, ulog->kdb_block); + + indx_log->kdb_umagic = KDB_ULOG_MAGIC; + indx_log->kdb_entry_size = upd_size; + indx_log->kdb_entry_sno = cur_sno; + indx_log->kdb_time = upd->kdb_time = ktime; + indx_log->kdb_commit = upd->kdb_commit = FALSE; + + ulog->kdb_state = KDB_UNSTABLE; + + xdrmem_create(&xdrs, (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_ENCODE); + if (!xdr_kdb_incr_update_t(&xdrs, upd)) + return (KRB5_LOG_CONV); + + if ((retval = ulog_sync_update(ulog, indx_log))) + return (retval); + + if (ulog->kdb_num < ulogentries) + ulog->kdb_num++; + + ulog->kdb_last_sno = cur_sno; + ulog->kdb_last_time = ktime; + + /* + * Since this is a circular array, once we circled, kdb_first_sno is + * always kdb_entry_sno + 1. + */ + if (cur_sno > ulogentries) { + i = upd->kdb_entry_sno % ulogentries; + indx_log = (kdb_ent_header_t *)INDEX(ulog, i); + ulog->kdb_first_sno = indx_log->kdb_entry_sno; + ulog->kdb_first_time = indx_log->kdb_time; + } else if (cur_sno == 1) { + ulog->kdb_first_sno = 1; + ulog->kdb_first_time = indx_log->kdb_time; + } + + ulog_sync_header(ulog); + + return (0); +} + +/* + * Mark the log entry as committed and sync the memory mapped log + * to file. + */ +krb5_error_code +ulog_finish_update(krb5_context context, kdb_incr_update_t *upd) +{ + krb5_error_code retval; + kdb_ent_header_t *indx_log; + uint_t i; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + uint32_t ulogentries; + + INIT_ULOG(context); + ulogentries = log_ctx->ulogentries; + + i = (upd->kdb_entry_sno - 1) % ulogentries; + + indx_log = (kdb_ent_header_t *)INDEX(ulog, i); + + indx_log->kdb_commit = TRUE; + + ulog->kdb_state = KDB_STABLE; + + if ((retval = ulog_sync_update(ulog, indx_log))) + return (retval); + + ulog_sync_header(ulog); + + return (0); +} + +/* + * Set the header log details on the slave and sync it to file. + */ +static void +ulog_finish_update_slave(kdb_hlog_t *ulog, kdb_last_t lastentry) +{ + + ulog->kdb_last_sno = lastentry.last_sno; + ulog->kdb_last_time = lastentry.last_time; + + ulog_sync_header(ulog); +} + +/* + * Delete an entry to the update log. + */ +krb5_error_code +ulog_delete_update(krb5_context context, kdb_incr_update_t *upd) +{ + + upd->kdb_deleted = TRUE; + + return (ulog_add_update(context, upd)); +} + +/* + * Used by the slave or master (during ulog_check) to update it's hash db from + * the incr update log. + * + * Must be called with lock held. + */ +krb5_error_code +ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args) +{ + krb5_db_entry *entry = NULL; + kdb_incr_update_t *upd = NULL, *fupd; + int i, no_of_updates; + krb5_error_code retval; + krb5_principal dbprinc = NULL; + kdb_last_t errlast; + char *dbprincstr = NULL; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + + INIT_ULOG(context); + + no_of_updates = incr_ret->updates.kdb_ulog_t_len; + upd = incr_ret->updates.kdb_ulog_t_val; + fupd = upd; + + /* + * We reset last_sno and last_time to 0, if krb5_db2_db_put_principal + * or krb5_db2_db_delete_principal fail. + */ + errlast.last_sno = (unsigned int)0; + errlast.last_time.seconds = (unsigned int)0; + errlast.last_time.useconds = (unsigned int)0; + + if ((retval = krb5_db_open(context, db_args, + KRB5_KDB_OPEN_RW|KRB5_KDB_SRV_TYPE_ADMIN))) + goto cleanup; + + for (i = 0; i < no_of_updates; i++) { + int nentry = 1; + + if (!upd->kdb_commit) + continue; + + if (upd->kdb_deleted) { + dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len + + 1) * sizeof (char)); + + if (dbprincstr == NULL) { + retval = ENOMEM; + goto cleanup; + } + + (void) strncpy(dbprincstr, + (char *)upd->kdb_princ_name.utf8str_t_val, + (upd->kdb_princ_name.utf8str_t_len + 1)); + dbprincstr[upd->kdb_princ_name.utf8str_t_len] = 0; + + if ((retval = krb5_parse_name(context, dbprincstr, + &dbprinc))) { + goto cleanup; + } + + free(dbprincstr); + + retval = krb5int_delete_principal_no_log(context, + dbprinc, + &nentry); + + if (dbprinc) { + krb5_free_principal(context, dbprinc); + dbprinc = NULL; + } + + if (retval) + goto cleanup; + } else { + entry = (krb5_db_entry *)malloc(sizeof (krb5_db_entry)); + + if (!entry) { + retval = errno; + goto cleanup; + } + + (void) memset(entry, 0, sizeof (krb5_db_entry)); + + if ((retval = ulog_conv_2dbentry(context, entry, upd, 1))) + goto cleanup; + + retval = krb5int_put_principal_no_log(context, entry, + &nentry); + + if (entry) { + krb5_db_free_principal(context, entry, nentry); + free(entry); + entry = NULL; + } + if (retval) + goto cleanup; + } + + upd++; + } + +cleanup: + if (fupd) + ulog_free_entries(fupd, no_of_updates); + + if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) { + if (retval) + ulog_finish_update_slave(ulog, errlast); + else + ulog_finish_update_slave(ulog, incr_ret->lastentry); + } + + return (retval); +} + +/* + * Validate the log file and resync any uncommitted update entries + * to the principal database. + * + * Must be called with lock held. + */ +static krb5_error_code +ulog_check(krb5_context context, kdb_hlog_t *ulog, char **db_args) +{ + XDR xdrs; + krb5_error_code retval = 0; + unsigned int i; + kdb_ent_header_t *indx_log; + kdb_incr_update_t *upd = NULL; + kdb_incr_result_t *incr_ret = NULL; + + ulog->kdb_state = KDB_STABLE; + + for (i = 0; i < ulog->kdb_num; i++) { + indx_log = (kdb_ent_header_t *)INDEX(ulog, i); + + if (indx_log->kdb_umagic != KDB_ULOG_MAGIC) { + /* + * Update entry corrupted we should scream and die + */ + ulog->kdb_state = KDB_CORRUPT; + retval = KRB5_LOG_CORRUPT; + break; + } + + if (indx_log->kdb_commit == FALSE) { + ulog->kdb_state = KDB_UNSTABLE; + + incr_ret = (kdb_incr_result_t *) + malloc(sizeof (kdb_incr_result_t)); + if (incr_ret == NULL) { + retval = errno; + goto error; + } + + upd = (kdb_incr_update_t *) + malloc(sizeof (kdb_incr_update_t)); + if (upd == NULL) { + retval = errno; + goto error; + } + + (void) memset(upd, 0, sizeof (kdb_incr_update_t)); + xdrmem_create(&xdrs, (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_DECODE); + if (!xdr_kdb_incr_update_t(&xdrs, upd)) { + retval = KRB5_LOG_CONV; + goto error; + } + + incr_ret->updates.kdb_ulog_t_len = 1; + incr_ret->updates.kdb_ulog_t_val = upd; + + upd->kdb_commit = TRUE; + + /* + * We don't want to readd this update and just use the + * existing update to be propagated later on + */ + ulog_set_role(context, IPROP_NULL); + retval = ulog_replay(context, incr_ret, db_args); + + /* + * upd was freed by ulog_replay, we NULL + * the pointer in case we subsequently break from loop. + */ + upd = NULL; + if (incr_ret) { + free(incr_ret); + incr_ret = NULL; + } + ulog_set_role(context, IPROP_MASTER); + + if (retval) + goto error; + + /* + * We flag this as committed since this was + * the last entry before kadmind crashed, ergo + * the slaves have not seen this update before + */ + indx_log->kdb_commit = TRUE; + retval = ulog_sync_update(ulog, indx_log); + if (retval) + goto error; + + ulog->kdb_state = KDB_STABLE; + } + } + +error: + if (upd) + ulog_free_entries(upd, 1); + + free(incr_ret); + + ulog_sync_header(ulog); + + return (retval); +} + +/* + * Map the log file to memory for performance and simplicity. + * + * Called by: if iprop_enabled then ulog_map(); + * Assumes that the caller will terminate on ulog_map, hence munmap and + * closing of the fd are implicitly performed by the caller. + * Returns 0 on success else failure. + */ +krb5_error_code +ulog_map(krb5_context context, const char *logname, uint32_t ulogentries, + int caller, char **db_args) +{ + struct stat st; + krb5_error_code retval; + uint32_t ulog_filesize; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + int ulogfd = -1; + + ulog_filesize = sizeof (kdb_hlog_t); + + if (stat(logname, &st) == -1) { + + if (caller == FKPROPLOG) { + /* + * File doesn't exist so we exit with kproplog + */ + return (errno); + } + + if ((ulogfd = open(logname, O_RDWR+O_CREAT, 0600)) == -1) { + return (errno); + } + + if (lseek(ulogfd, 0L, SEEK_CUR) == -1) { + return (errno); + } + + if ((caller == FKADMIND) || (caller == FKCOMMAND)) + ulog_filesize += ulogentries * ULOG_BLOCK; + + if (extend_file_to(ulogfd, ulog_filesize) < 0) + return errno; + } else { + + ulogfd = open(logname, O_RDWR, 0600); + if (ulogfd == -1) + /* + * Can't open existing log file + */ + return errno; + } + + if (caller == FKPROPLOG) { + if (fstat(ulogfd, &st) < 0) { + close(ulogfd); + return errno; + } + ulog_filesize = st.st_size; + + ulog = (kdb_hlog_t *)mmap(0, ulog_filesize, + PROT_READ+PROT_WRITE, MAP_PRIVATE, ulogfd, 0); + } else { + /* + * else kadmind, kpropd, & kcommands should udpate stores + */ + ulog = (kdb_hlog_t *)mmap(0, MAXLOGLEN, + PROT_READ+PROT_WRITE, MAP_SHARED, ulogfd, 0); + } + + if ((int)(ulog) == -1) { + /* + * Can't map update log file to memory + */ + close(ulogfd); + return (errno); + } + + if (!context->kdblog_context) { + if (!(log_ctx = malloc(sizeof (kdb_log_context)))) + return (errno); + memset(log_ctx, 0, sizeof(*log_ctx)); + context->kdblog_context = log_ctx; + } else + log_ctx = context->kdblog_context; + log_ctx->ulog = ulog; + log_ctx->ulogentries = ulogentries; + log_ctx->ulogfd = ulogfd; + + if (ulog->kdb_hmagic != KDB_ULOG_HDR_MAGIC) { + if (ulog->kdb_hmagic == 0) { + /* + * New update log + */ + (void) memset(ulog, 0, sizeof (kdb_hlog_t)); + + ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + ulog->db_version_num = KDB_VERSION; + ulog->kdb_state = KDB_STABLE; + ulog->kdb_block = ULOG_BLOCK; + if (!(caller == FKPROPLOG)) + ulog_sync_header(ulog); + } else { + return (KRB5_LOG_CORRUPT); + } + } + + if (caller == FKADMIND) { + retval = ulog_lock(context, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) + return retval; + switch (ulog->kdb_state) { + case KDB_STABLE: + case KDB_UNSTABLE: + /* + * Log is currently un/stable, check anyway + */ + retval = ulog_check(context, ulog, db_args); + ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + if (retval == KRB5_LOG_CORRUPT) { + return (retval); + } + break; + case KDB_CORRUPT: + ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return (KRB5_LOG_CORRUPT); + default: + /* + * Invalid db state + */ + ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return (KRB5_LOG_ERROR); + } + } else if ((caller == FKPROPLOG) || (caller == FKPROPD)) { + /* + * kproplog and kpropd don't need to do anything else + */ + return (0); + } + + /* + * Reinit ulog if the log is being truncated or expanded after + * we have circled. + */ + retval = ulog_lock(context, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) + return retval; + if (ulog->kdb_num != ulogentries) { + if ((ulog->kdb_num != 0) && + ((ulog->kdb_last_sno > ulog->kdb_num) || + (ulog->kdb_num > ulogentries))) { + + (void) memset(ulog, 0, sizeof (kdb_hlog_t)); + + ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + ulog->db_version_num = KDB_VERSION; + ulog->kdb_state = KDB_STABLE; + ulog->kdb_block = ULOG_BLOCK; + + ulog_sync_header(ulog); + } + + /* + * Expand ulog if we have specified a greater size + */ + if (ulog->kdb_num < ulogentries) { + ulog_filesize += ulogentries * ulog->kdb_block; + + if (extend_file_to(ulogfd, ulog_filesize) < 0) { + ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return errno; + } + } + } + ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + + return (0); +} + +/* + * Get the last set of updates seen, (last+1) to n is returned. + */ +krb5_error_code +ulog_get_entries(krb5_context context, /* input - krb5 lib config */ + kdb_last_t last, /* input - slave's last sno */ + kdb_incr_result_t *ulog_handle) /* output - incr result for slave */ +{ + XDR xdrs; + kdb_ent_header_t *indx_log; + kdb_incr_update_t *upd; + uint_t indx, count, tdiff; + uint32_t sno; + krb5_error_code retval; + struct timeval timestamp; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + uint32_t ulogentries; + + INIT_ULOG(context); + ulogentries = log_ctx->ulogentries; + + retval = ulog_lock(context, KRB5_LOCKMODE_SHARED); + if (retval) + return retval; + + /* + * Check to make sure we don't have a corrupt ulog first. + */ + if (ulog->kdb_state == KDB_CORRUPT) { + ulog_handle->ret = UPDATE_ERROR; + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return (KRB5_LOG_CORRUPT); + } + + gettimeofday(×tamp, NULL); + + tdiff = timestamp.tv_sec - ulog->kdb_last_time.seconds; + if (tdiff <= ULOG_IDLE_TIME) { + ulog_handle->ret = UPDATE_BUSY; + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return (0); + } + + /* + * We need to lock out other processes here, such as kadmin.local, + * since we are looking at the last_sno and looking up updates. So + * we can share with other readers. + */ + retval = krb5_db_lock(context, KRB5_LOCKMODE_SHARED); + if (retval) { + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + return (retval); + } + + /* + * We may have overflowed the update log or we shrunk the log, or + * the client's ulog has just been created. + */ + if ((last.last_sno > ulog->kdb_last_sno) || + (last.last_sno < ulog->kdb_first_sno) || + (last.last_sno == 0)) { + ulog_handle->lastentry.last_sno = ulog->kdb_last_sno; + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED; + return (0); + } else if (last.last_sno <= ulog->kdb_last_sno) { + sno = last.last_sno; + + indx = (sno - 1) % ulogentries; + + indx_log = (kdb_ent_header_t *)INDEX(ulog, indx); + + /* + * Validate the time stamp just to make sure it was the same sno + */ + if ((indx_log->kdb_time.seconds == last.last_time.seconds) && + (indx_log->kdb_time.useconds == last.last_time.useconds)) { + + /* + * If we have the same sno we return success + */ + if (last.last_sno == ulog->kdb_last_sno) { + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + ulog_handle->ret = UPDATE_NIL; + return (0); + } + + count = ulog->kdb_last_sno - sno; + + ulog_handle->updates.kdb_ulog_t_val = + (kdb_incr_update_t *)malloc( + sizeof (kdb_incr_update_t) * count); + + upd = ulog_handle->updates.kdb_ulog_t_val; + + if (upd == NULL) { + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + ulog_handle->ret = UPDATE_ERROR; + return (errno); + } + + while (sno < ulog->kdb_last_sno) { + indx = sno % ulogentries; + + indx_log = (kdb_ent_header_t *) + INDEX(ulog, indx); + + (void) memset(upd, 0, + sizeof (kdb_incr_update_t)); + xdrmem_create(&xdrs, + (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_DECODE); + if (!xdr_kdb_incr_update_t(&xdrs, upd)) { + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + ulog_handle->ret = UPDATE_ERROR; + return (KRB5_LOG_CONV); + } + /* + * Mark commitment since we didn't + * want to decode and encode the + * incr update record the first time. + */ + upd->kdb_commit = indx_log->kdb_commit; + + upd++; + sno++; + } /* while */ + + ulog_handle->updates.kdb_ulog_t_len = count; + + ulog_handle->lastentry.last_sno = ulog->kdb_last_sno; + ulog_handle->lastentry.last_time.seconds = + ulog->kdb_last_time.seconds; + ulog_handle->lastentry.last_time.useconds = + ulog->kdb_last_time.useconds; + ulog_handle->ret = UPDATE_OK; + + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + + return (0); + } else { + /* + * We have time stamp mismatch or we no longer have + * the slave's last sno, so we brute force it + */ + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + (void) krb5_db_unlock(context); + ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED; + + return (0); + } + } + + /* + * Should never get here, return error + */ + (void) ulog_lock(context, KRB5_LOCKMODE_UNLOCK); + ulog_handle->ret = UPDATE_ERROR; + return (KRB5_LOG_ERROR); +} + +krb5_error_code +ulog_set_role(krb5_context ctx, iprop_role role) +{ + kdb_log_context *log_ctx; + + if (!ctx->kdblog_context) { + if (!(log_ctx = malloc(sizeof (kdb_log_context)))) + return (errno); + memset(log_ctx, 0, sizeof(*log_ctx)); + ctx->kdblog_context = log_ctx; + } else + log_ctx = ctx->kdblog_context; + + log_ctx->iproprole = role; + + return (0); +} + +/* + * Extend update log file. + */ +static int extend_file_to(int fd, uint_t new_size) +{ + int current_offset; + static const char zero[512] = { 0, }; + + current_offset = lseek(fd, 0, SEEK_END); + if (current_offset < 0) + return -1; + if (new_size > INT_MAX) { + errno = EINVAL; + return -1; + } + while (current_offset < new_size) { + int write_size, wrote_size; + write_size = new_size - current_offset; + if (write_size > 512) + write_size = 512; + wrote_size = write(fd, zero, write_size); + if (wrote_size < 0) + return -1; + if (wrote_size == 0) { + errno = EINVAL; /* XXX ?? */ + return -1; + } + current_offset += wrote_size; + write_size = new_size - current_offset; + } + return 0; +} diff --git a/krb5-1-7/src/lib/kdb/keytab.c b/krb5-1-7/src/lib/kdb/keytab.c new file mode 100644 index 000000000..47626f152 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/keytab.c @@ -0,0 +1,242 @@ +/* + * 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 + +#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 (strlcpy(name, "KDB:", namelen) >= namelen); + return KRB5_KT_NAME_TOOLONG; + 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; + free(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_keylist_node * master_keylist; + 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_list(context, &master_keylist); + if (kerror) + goto error; + + kerror = krb5_dbe_find_mkey(context, master_keylist, &db_entry, &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 == KRB5_KDB_NO_MATCHING_KEY) + kerror = KRB5_KT_KVNONOTFOUND; + 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-7/src/lib/kdb/libkdb5.exports b/krb5-1-7/src/lib/kdb/libkdb5.exports new file mode 100644 index 000000000..a1fd4d5e8 --- /dev/null +++ b/krb5-1-7/src/lib/kdb/libkdb5.exports @@ -0,0 +1,85 @@ +krb5_db_setup_lib_handle +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_fetch_mkey_list +krb5_db_free_mkey_list +krb5_db_fini +krb5_db_free_principal +krb5_db_get_age +krb5_db_get_key_data_kvno +krb5_db_get_mkey +krb5_db_get_mkey_list +krb5_db_get_context +krb5_db_get_principal +krb5_db_get_principal_ext +krb5_db_invoke +krb5_db_iterate +krb5_db_lock +krb5_db_put_principal +krb5_db_set_context +krb5_db_set_mkey +krb5_db_set_mkey_list +krb5_db_setup_mkey_name +krb5_db_unlock +krb5_db_store_master_key +krb5_db_store_master_key_list +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_act_mkey +krb5_dbe_fetch_act_key_list +krb5_dbe_find_enctype +krb5_dbe_find_mkey +krb5_dbe_free_actkvno_list +krb5_dbe_free_key_data_contents +krb5_dbe_free_mkey_aux_list +krb5_dbe_free_key_list +krb5_dbe_lookup_last_pwd_change +krb5_dbe_lookup_actkvno +krb5_dbe_lookup_mkey_aux +krb5_dbe_lookup_mkvno +krb5_dbe_lookup_mod_princ_data +krb5_dbe_lookup_tl_data +krb5_dbe_search_enctype +krb5_dbe_update_actkvno +krb5_dbe_update_last_pwd_change +krb5_dbe_update_mkey_aux +krb5_dbe_update_mkvno +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_def_store_mkey_list +krb5_db_promote +ulog_map +ulog_set_role +ulog_free_entries +xdr_kdb_last_t +xdr_kdb_incr_result_t +xdr_kdb_fullresync_result_t +ulog_get_entries +ulog_replay +xdr_kdb_incr_update_t diff --git a/krb5-1-7/src/lib/krb4_32.def b/krb5-1-7/src/lib/krb4_32.def new file mode 100644 index 000000000..11814cebd --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5.rc b/krb5-1-7/src/lib/krb5.rc new file mode 100644 index 000000000..f8e540024 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/Makefile.in b/krb5-1-7/src/lib/krb5/Makefile.in new file mode 100644 index 000000000..75a142973 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/Makefile.in @@ -0,0 +1,138 @@ +thisconfigdir=../.. +myfulldir=lib/krb5 +mydir=lib/krb5 +BUILDTOP=$(REL)..$(S).. +LOCALINCLUDES = -I$(srcdir)/ccache -I$(srcdir)/keytab -I$(srcdir)/rcache -I$(srcdir)/os -I$(srcdir)/unicode +SUBDIRS= error_tables asn.1 ccache keytab krb os rcache unicode +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 \ + unicode/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 \ + unicode/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 ..\unicode + @echo Making in krb5\unicode + $(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 ..\unicode + @echo Making clean in krb5\unicode + $(MAKE) -$(MFLAGS) clean + cd .. + @echo Making clean locally + +install-unix:: install-libs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/krb5/asn.1/KRB5-asn.py b/krb5-1-7/src/lib/krb5/asn.1/KRB5-asn.py new file mode 100644 index 000000000..e455fd9a1 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/asn.1/Makefile.in b/krb5-1-7/src/lib/krb5/asn.1/Makefile.in new file mode 100644 index 000000000..f7f1b2195 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/Makefile.in @@ -0,0 +1,59 @@ +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@ + diff --git a/krb5-1-7/src/lib/krb5/asn.1/TODO.asn1 b/krb5-1-7/src/lib/krb5/asn.1/TODO.asn1 new file mode 100644 index 000000000..73f5fed7a --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/TODO.asn1 @@ -0,0 +1,90 @@ +-*- text -*- + +Stuff that should still be done on the ASN.1 encoder conversion: + +* Add support for opaque objects (pre-encoded fields, or ANY), and fix + up those remaining encoders (e.g., asn1_encode_sam_challenge_2) that + need them. + +* Convert PKINIT encoders, after we have test cases. + +* Make offsetof uses conforming. Currently we may use foo.bar or + foo[0] as fields. + +* Script to generate the tables. Then each type or field entry can + generate multiple bits of code, instead of forcing us to bury the + type consistency checking into the structure initializer + expression. For example, we might generate these bits of code from + one field descriptor: + + * Field table entry. + + * Type-checking code: Create a pointer of the expected type and a + pointer of the actual type (address of field of automatic struct), + and verify consistency with comparison, assignment, or conditional + expr. Plenty of comments to indicate what's being compared and + what a compiler complain means. + + * Range-checking code for bitfields: Create an automatic field info + struct, fill in the computed offset or whatever, read it back, + make sure it matches. Also with comments. + + * Possibly header declarations describing the types that could be + imported, with correct handles *and* C types. + + * Static declarations for non-exported types to keep symbol table + sizes down. + + Then similar bits of code (e.g., all the field table entries) can be + pulled together into the appropriate places. + +* Some kind of "module" system for exporting and importing encoders, + better than relying on the "type_*" variable names. Probably use + meaningful strings that indicate both the ASN.1 type and the + associated C type. Find a way to fit "imported type" into this + scheme so that we can cleanly move the PKINIT types into the PKINIT + plugin, the LDAP types into the LDAP plugin, etc., and still let + them use the encoders in the code. Only a subset of types would be + exported probably. + +* More compact encoding: For tags and optional-field bit positions, + encode N+1, and use 0 for "none", then make the field unsigned. + Currently the fields are signed, non-negative values hold useful + data, -1 means "none", and MIN..-2 are unused. Changing this will + either let us reduce the field size one bit, or extend the maximum + tag/bitpos value from 2**(N-1)-1 to 2**N-2. + +* More compact encoding: Use a union with designated initializers, or + some ugly casting, to make the structures smaller by not having all + fields present when we never use all of them at once. The union + approach is certainly more appealing, aside from the little detail + that it won't work on Windows unless we do all the initialization at + run time. + +* Pie in the sky: A verbose mode that can tell you "missing field + KDC-REP.cname.name-string[1].data" or some such. This would require + tracking the stack of pending encodes and adding strings with type + and field names. + +* For ALL_POINTERS_ARE_THE_SAME mode (which is not strictly conforming + with the C standard, and thus not default currently, but makes + things a little smaller and faster), eliminate the loadptr structure + entry. + +* Maybe: Reorganize the data of a "module" so everything needing + relocation is put in some tables, referenced by index from other + structures without relocations. E.g., for krb5_data, here's the + offset for the data pointer, here's the offset for the length value, + here's the index into the pointer reader function table, here's the + index into the length reader function table, here's an index into + the string-type encoder table. + + Using an index into a set of pointer types, with a single function + taking an integer parameter used to switch between various + ptr-to-ptr-to-type code paths, will be a lot smaller -- with a good + compiler the function will probably collapse to a simple + fetch-a-pointer function ignoring the integer argument, while at the + C level it's strictly conforming by using the correct types for + access. + +* Table-driven decoders? diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.c new file mode 100644 index 000000000..032e82734 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.c @@ -0,0 +1,277 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 "k5-int.h" /* for krb5int_gmt_mktime */ +#include "asn1_decode.h" +#include "asn1_get.h" +#include +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#include +#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 + +asn1_error_code asn1_decode_integer(asn1buf *buf, long int *val) +{ + setup(); + asn1_octet o; + long n = 0; /* initialize to keep gcc happy */ + unsigned 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; + unsigned 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); + if (retval) return retval; + /* 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(); +} + +asn1_error_code asn1_decode_boolean(asn1buf *buf, unsigned *val) +{ + setup(); + asn1_octet bval; + + tag(ASN1_BOOLEAN); + + retval = asn1buf_remove_octet(buf, &bval); + if (retval) return retval; + + *val = (bval != 0x00); + + cleanup(); +} diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.h new file mode 100644 index 000000000..b90a369d6 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_decode.h @@ -0,0 +1,96 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 (). + 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_boolean + (asn1buf *buf, unsigned int *val); +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-7/src/lib/krb5/asn.1/asn1_encode.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_encode.c new file mode 100644 index 000000000..f67c8cfee --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_encode.c @@ -0,0 +1,700 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/asn1_encode.c + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" + +asn1_error_code asn1_encode_boolean(asn1buf *buf, asn1_intmax val, + unsigned int *retlen) +{ + asn1_error_code retval; + unsigned int length = 0; + unsigned int partlen = 1; + asn1_octet bval; + + bval = val ? 0xFF : 0x00; + + retval = asn1buf_insert_octet(buf, bval); + if (retval) return retval; + + length = partlen; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BOOLEAN, length, &partlen); + if (retval) return retval; + length += partlen; + + *retlen = length; + return 0; +} + +static asn1_error_code asn1_encode_integer_internal(asn1buf *buf, + asn1_intmax 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, asn1_intmax 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; +} + +#if 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; +} +#endif + +asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax 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); + + 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; +} + +static asn1_error_code +encode_bytestring_with_tag(asn1buf *buf, unsigned int len, + const void *val, int tag, + unsigned int *retlen) +{ + asn1_error_code retval; + unsigned int length; + + if (len > 0 && val == 0) return ASN1_MISSING_FIELD; + retval = asn1buf_insert_octetstring(buf, len, val); + if (retval) return retval; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, tag, + len, &length); + if (retval) return retval; + + *retlen = len + length; + return 0; +} + +asn1_error_code asn1_encode_oid(asn1buf *buf, unsigned int len, + const asn1_octet *val, + unsigned int *retlen) +{ + return encode_bytestring_with_tag(buf, len, val, ASN1_OBJECTIDENTIFIER, + retlen); +} + +asn1_error_code asn1_encode_octetstring(asn1buf *buf, unsigned int len, + const void *val, + unsigned int *retlen) +{ + return encode_bytestring_with_tag(buf, len, val, ASN1_OCTETSTRING, + retlen); +} + +#if 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) +{ + return encode_bytestring_with_tag(buf, len, val, ASN1_PRINTABLESTRING, + retlen); +} + +asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len, + const char *val, int *retlen) +{ + return encode_bytestring_with_tag(buf, len, val, ASN1_IA5STRING, + retlen); +} +#endif + +asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, + unsigned int *retlen) +{ + struct tm *gtime, gtimebuf; + char s[16], *sp; + time_t gmt_time = val; + + /* + * Time encoding: YYYYMMDDhhmmssZ + */ + if (gmt_time == 0) { + sp = "19700101000000Z"; + } else { + int len; + + /* + * 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; + len = snprintf(s, sizeof(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); + if (SNPRINTF_OVERFLOW(len, sizeof(s))) + /* Shouldn't be possible given above tests. */ + return ASN1_BAD_GMTIME; + sp = s; + } + + return encode_bytestring_with_tag(buf, 15, sp, ASN1_GENERALTIME, + retlen); +} + +asn1_error_code asn1_encode_generalstring(asn1buf *buf, unsigned int len, + const void *val, + unsigned int *retlen) +{ + return encode_bytestring_with_tag(buf, len, val, ASN1_GENERALSTRING, + retlen); +} + +asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, + const void *val, + unsigned int *retlen) +{ + asn1_error_code retval; + unsigned int length; + + retval = asn1buf_insert_octetstring(buf, len, val); + if (retval) return retval; + retval = asn1buf_insert_octet(buf, 0); + if (retval) return retval; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BITSTRING, + len+1, &length); + if (retval) return retval; + *retlen = len + 1 + length; + return 0; +} + +asn1_error_code asn1_encode_opaque(asn1buf *buf, unsigned int len, + const void *val, unsigned int *retlen) +{ + asn1_error_code retval; + + retval = asn1buf_insert_octetstring(buf, len, val); + if (retval) return retval; + *retlen = len; + return 0; +} + +/* ASN.1 constructed type encoder engine + + Two entry points here: + + krb5int_asn1_encode_a_thing: Incrementally adds the partial + encoding of an object to an already-initialized asn1buf. + + krb5int_asn1_do_full_encode: Returns a completed encoding, in the + correct byte order, in an allocated krb5_data. */ + +#ifdef POINTERS_ARE_ALL_THE_SAME +#define LOADPTR(PTR,TYPE) \ + (assert((TYPE)->loadptr != NULL), (TYPE)->loadptr(PTR)) +#else +#define LOADPTR(PTR,TYPE) \ + (*(const void *const *)(PTR)) +#endif + +static int +get_nullterm_sequence_len(const void *valp, const struct atype_info *seq) +{ + int i; + const struct atype_info *a; + const void *elt, *eltptr; + + a = seq; + i = 0; + assert(a->type == atype_ptr); + assert(seq->size != 0); + + while (1) { + eltptr = (const char *) valp + i * seq->size; + elt = LOADPTR(eltptr, a); + if (elt == NULL) + break; + i++; + } + return i; +} +static asn1_error_code +encode_sequence_of(asn1buf *buf, int seqlen, const void *val, + const struct atype_info *eltinfo, + unsigned int *retlen); + +static asn1_error_code +encode_nullterm_sequence_of(asn1buf *buf, const void *val, + const struct atype_info *type, + int can_be_empty, + unsigned int *retlen) +{ + int length = get_nullterm_sequence_len(val, type); + if (!can_be_empty && length == 0) return ASN1_MISSING_FIELD; + return encode_sequence_of(buf, length, val, type, retlen); +} + +static asn1_error_code +just_encode_sequence(asn1buf *buf, const void *val, + const struct seq_info *seq, + unsigned int *retlen); +static asn1_error_code +encode_a_field(asn1buf *buf, const void *val, + const struct field_info *field, + unsigned int *retlen); + +asn1_error_code +krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, + const struct atype_info *a, unsigned int *retlen) +{ + switch (a->type) { + case atype_fn: + assert(a->enc != NULL); + return a->enc(buf, val, retlen); + case atype_sequence: + assert(a->seq != NULL); + return just_encode_sequence(buf, val, a->seq, retlen); + case atype_ptr: + assert(a->basetype != NULL); + return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, a), + a->basetype, retlen); + case atype_field: + assert(a->field != NULL); + return encode_a_field(buf, val, a->field, retlen); + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + assert(a->basetype != NULL); + return encode_nullterm_sequence_of(buf, val, a->basetype, + a->type == atype_nullterm_sequence_of, + retlen); + case atype_tagged_thing: + { + asn1_error_code retval; + unsigned int length, sum = 0; + retval = krb5int_asn1_encode_a_thing(buf, val, a->basetype, &length); + if (retval) return retval; + sum = length; + retval = asn1_make_etag(buf, a->tagtype, a->tagval, sum, &length); + if (retval) return retval; + sum += length; + *retlen = sum; + return 0; + } + case atype_int: + assert(a->loadint != NULL); + return asn1_encode_integer(buf, a->loadint(val), retlen); + case atype_uint: + assert(a->loaduint != NULL); + return asn1_encode_unsigned_integer(buf, a->loaduint(val), retlen); + case atype_min: + case atype_max: + case atype_fn_len: + default: + assert(a->type > atype_min); + assert(a->type < atype_max); + assert(a->type != atype_fn_len); + abort(); + } +} + +static asn1_error_code +encode_a_field(asn1buf *buf, const void *val, + const struct field_info *field, + unsigned int *retlen) +{ + asn1_error_code retval; + unsigned int sum = 0; + + if (val == NULL) return ASN1_MISSING_FIELD; + + switch (field->ftype) { + case field_immediate: + { + unsigned int length; + + retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff, + &length); + if (retval) return retval; + sum += length; + break; + } + case field_sequenceof_len: + { + const void *dataptr, *lenptr; + int slen; + unsigned int length; + const struct atype_info *a; + + /* The field holds a pointer to the array of objects. So the + address we compute is a pointer-to-pointer, and that's what + field->atype must help us dereference. */ + dataptr = (const char *)val + field->dataoff; + lenptr = (const char *)val + field->lenoff; + assert(field->atype->type == atype_ptr); + dataptr = LOADPTR(dataptr, field->atype); + a = field->atype->basetype; + assert(field->lentype != 0); + assert(field->lentype->type == atype_int || field->lentype->type == atype_uint); + assert(sizeof(int) <= sizeof(asn1_intmax)); + assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); + if (field->lentype->type == atype_int) { + asn1_intmax xlen = field->lentype->loadint(lenptr); + if (xlen < 0) + return EINVAL; + if ((unsigned int) xlen != (asn1_uintmax) xlen) + return EINVAL; + if ((unsigned int) xlen > INT_MAX) + return EINVAL; + slen = (int) xlen; + } else { + asn1_uintmax xlen = field->lentype->loaduint(lenptr); + if ((unsigned int) xlen != xlen) + return EINVAL; + if (xlen > INT_MAX) + return EINVAL; + slen = (int) xlen; + } + if (slen != 0 && dataptr == NULL) + return ASN1_MISSING_FIELD; + retval = encode_sequence_of(buf, slen, dataptr, a, &length); + if (retval) return retval; + sum += length; + break; + } + case field_normal: + { + const void *dataptr; + const struct atype_info *a; + unsigned int length; + + dataptr = (const char *)val + field->dataoff; + + a = field->atype; + assert(a->type != atype_fn_len); + retval = krb5int_asn1_encode_a_thing(buf, dataptr, a, &length); + if (retval) { + return retval; + } + sum += length; + break; + } + case field_string: + { + const void *dataptr, *lenptr; + const struct atype_info *a; + size_t slen; + unsigned int length; + + dataptr = (const char *)val + field->dataoff; + lenptr = (const char *)val + field->lenoff; + + a = field->atype; + assert(a->type == atype_fn_len); + assert(field->lentype != 0); + assert(field->lentype->type == atype_int || field->lentype->type == atype_uint); + assert(sizeof(int) <= sizeof(asn1_intmax)); + assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); + if (field->lentype->type == atype_int) { + asn1_intmax xlen = field->lentype->loadint(lenptr); + if (xlen < 0) + return EINVAL; + if ((size_t) xlen != (asn1_uintmax) xlen) + return EINVAL; + slen = (size_t) xlen; + } else { + asn1_uintmax xlen = field->lentype->loaduint(lenptr); + if ((size_t) xlen != xlen) + return EINVAL; + slen = (size_t) xlen; + } + + dataptr = LOADPTR(dataptr, a); + if (slen == SIZE_MAX) + /* Error - negative or out of size_t range. */ + return EINVAL; + if (dataptr == NULL && slen != 0) + return ASN1_MISSING_FIELD; + /* Currently our string encoders want "unsigned int" for + lengths. */ + if (slen != (unsigned int) slen) + return EINVAL; + assert(a->enclen != NULL); + retval = a->enclen(buf, (unsigned int) slen, dataptr, &length); + if (retval) { + return retval; + } + sum += length; + break; + } + default: + assert(field->ftype > field_min); + assert(field->ftype < field_max); + assert(__LINE__ == 0); + abort(); + } + if (field->tag >= 0) { + unsigned int length; + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, field->tag, sum, + &length); + if (retval) { + return retval; + } + sum += length; + } + *retlen = sum; + return 0; +} + +static asn1_error_code +encode_fields(asn1buf *buf, const void *val, + const struct field_info *fields, size_t nfields, + unsigned int optional, + unsigned int *retlen) +{ + size_t i; + unsigned int sum = 0; + for (i = nfields; i > 0; i--) { + const struct field_info *f = fields+i-1; + unsigned int length; + asn1_error_code retval; + int present; + + if (f->opt == -1) + present = 1; + else if ((1u << f->opt) & optional) + present = 1; + else + present = 0; + if (present) { + retval = encode_a_field(buf, val, f, &length); + if (retval) return retval; + sum += length; + } + } + *retlen = sum; + return 0; +} + +static asn1_error_code +just_encode_sequence(asn1buf *buf, const void *val, + const struct seq_info *seq, + unsigned int *retlen) +{ + const struct field_info *fields = seq->fields; + size_t nfields = seq->n_fields; + unsigned int optional; + asn1_error_code retval; + unsigned int sum = 0; + + if (seq->optional) + optional = seq->optional(val); + else + /* In this case, none of the field descriptors should indicate + that we examine any bits of this value. */ + optional = 0; + { + unsigned int length; + retval = encode_fields(buf, val, fields, nfields, optional, &length); + if (retval) return retval; + sum += length; + } + { + unsigned int length; + retval = asn1_make_sequence(buf, sum, &length); + if (retval) return retval; + sum += length; + } + *retlen = sum; + return 0; +} + +static asn1_error_code +encode_sequence_of(asn1buf *buf, int seqlen, const void *val, + const struct atype_info *eltinfo, + unsigned int *retlen) +{ + asn1_error_code retval; + unsigned int sum = 0; + int i; + + for (i = seqlen-1; i >= 0; i--) { + const void *eltptr; + unsigned int length; + const struct atype_info *a = eltinfo; + + assert(eltinfo->size != 0); + eltptr = (const char *)val + i * eltinfo->size; + retval = krb5int_asn1_encode_a_thing(buf, eltptr, a, &length); + if (retval) return retval; + sum += length; + } + { + unsigned int length; + retval = asn1_make_sequence(buf, sum, &length); + if (retval) return retval; + sum += length; + } + *retlen = sum; + return 0; +} + +krb5_error_code +krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, + const struct atype_info *a) +{ + unsigned int length; + asn1_error_code retval; + asn1buf *buf = NULL; + krb5_data *d; + + *code = NULL; + + if (rep == NULL) + return ASN1_MISSING_FIELD; + + retval = asn1buf_create(&buf); + if (retval) + return retval; + + retval = krb5int_asn1_encode_a_thing(buf, rep, a, &length); + if (retval) + goto cleanup; + retval = asn12krb5_buf(buf, &d); + if (retval) + goto cleanup; + *code = d; +cleanup: + asn1buf_destroy(&buf); + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_encode.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_encode.h new file mode 100644 index 000000000..289b98db1 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_encode.h @@ -0,0 +1,664 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/asn1_encode.h + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +/* + Overview + + Each of these procedures inserts the encoding of an ASN.1 + primitive in a coding buffer. + + Operations + + asn1_encode_boolean + asn1_encode_integer + asn1_encode_unsigned_integer + asn1_encode_octetstring + asn1_encode_generaltime + asn1_encode_generalstring + asn1_encode_bitstring + asn1_encode_oid +*/ + +asn1_error_code asn1_encode_boolean + (asn1buf *buf, asn1_intmax val, unsigned int *retlen); +asn1_error_code asn1_encode_integer + (asn1buf *buf, asn1_intmax 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, asn1_uintmax 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 void *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. */ +#define asn1_encode_charstring asn1_encode_octetstring + +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_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 void *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. */ + +asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, + const void *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. */ + +asn1_error_code asn1_encode_opaque(asn1buf *buf, unsigned int len, + const void *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. */ + +/* Type descriptor info. + + In this context, a "type" is a combination of a C data type + and an ASN.1 encoding scheme for it. So we would have to define + different "types" for: + + * unsigned char* encoded as octet string + * char* encoded as octet string + * char* encoded as generalstring + * krb5_data encoded as octet string + * krb5_data encoded as generalstring + * int32_t encoded as integer + * unsigned char encoded as integer + + Perhaps someday some kind of flags could be defined so that minor + variations on the C types could be handled via common routines. + + The handling of strings is pretty messy. Currently, we have a + separate kind of encoder function that takes an extra length + parameter. Perhaps we should just give up on that, always deal + with just a single location, and handle strings by via encoder + functions for krb5_data, keyblock, etc. + + We wind up with a lot of load-time relocations being done, which is + a bit annoying. Be careful about "fixing" that at the cost of too + much run-time performance. It might work to have a master "module" + descriptor with pointers to various arrays (type descriptors, + strings, field descriptors, functions) most of which don't need + relocation themselves, and replace most of the pointers with table + indices. + + It's a work in progress. */ + +enum atype_type { + /* For bounds checking only. By starting with values above 1, we + guarantee that zero-initialized storage will be recognized as + invalid. */ + atype_min = 1, + /* Encoder function to be called with address of . */ + atype_fn, + /* Encoder function to be called with address of and a + length (unsigned int). */ + atype_fn_len, + /* Pointer to actual thing to be encoded. + + Most of the fields are related only to the C type -- size, how + to fetch a pointer in a type-safe fashion -- but since the base + type descriptor encapsulates the encoding as well, different + encodings for the same C type may require different pointer-to + types as well. + + Must not refer to atype_fn_len. */ + atype_ptr, + /* Sequence, with pointer to sequence descriptor header. */ + atype_sequence, + /* Sequence-of, with pointer to base type descriptor, represented + as a null-terminated array of pointers (and thus the "base" + type descriptor is actually an atype_ptr node). */ + atype_nullterm_sequence_of, + atype_nonempty_nullterm_sequence_of, + /* Encode this object using a single field descriptor. This may + mean the atype/field breakdown needs revision.... + + Main expected uses: Encode realm component of principal as a + GENERALSTRING. Pluck data and length fields out of a structure + and encode a counted SEQUENCE OF. */ + atype_field, + /* Tagged version of another type. */ + atype_tagged_thing, + /* Integer types. */ + atype_int, + atype_uint, + /* Unused except for bounds checking. */ + atype_max +}; + +/* Initialized structures could be a lot smaller if we could use C99 + designated initializers, and a union for all the type-specific + stuff. Maybe use the hack we use for krb5int_access, where we use + a run-time initialize if the compiler doesn't support designated + initializers? That's a lot of work here, though, with so many + little structures. Maybe if/when these get auto-generated. */ +struct atype_info { + enum atype_type type; + /* used for sequence-of processing */ + unsigned int size; + /* atype_fn */ + asn1_error_code (*enc)(asn1buf *, const void *, unsigned int *); + /* atype_fn_len */ + asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *, + unsigned int *); + /* atype_ptr, atype_fn_len */ + const void *(*loadptr)(const void *); + /* atype_ptr, atype_nullterm_sequence_of */ + const struct atype_info *basetype; + /* atype_sequence */ + const struct seq_info *seq; + /* atype_field */ + const struct field_info *field; + /* atype_tagged_thing */ + unsigned int tagval : 8, tagtype : 8; + /* atype_[u]int */ + asn1_intmax (*loadint)(const void *); + asn1_uintmax (*loaduint)(const void *); +}; + +/* The various DEF*TYPE macros must: + + + Define a type named aux_typedefname_##DESCNAME, for use in any + types derived from the type being defined. + + + Define an atype_info struct named krb5int_asn1type_##DESCNAME. + + + Define any extra stuff needed in the type descriptor, like + pointer-load functions. + + + Accept a following semicolon syntactically, to keep Emacs parsing + (and indentation calculating) code happy. + + Nothing else should directly define the atype_info structures. */ + +/* Define a type for which we must use an explicit encoder function. + The DEFFNTYPE variant uses a function taking a void*, the + DEFFNXTYPE form wants a function taking a pointer to the actual C + type to be encoded; you should use the latter unless you've already + got the void* function supplied elsewhere. + + Of course, we need a single, consistent type for the descriptor + structure field, so we use the function pointer type that uses + void*, and create a wrapper function in DEFFNXTYPE. However, in + all our cases so far, the supplied function is static and not used + otherwise, so the compiler can merge it with the wrapper function + if the optimizer is good enough. */ +#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_fn, sizeof(CTYPENAME), ENCFN, \ + } +#define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static asn1_error_code \ + aux_encfn_##DESCNAME(asn1buf *buf, const void *val, \ + unsigned int *retlen) \ + { \ + return ENCFN(buf, \ + (const aux_typedefname_##DESCNAME *)val, \ + retlen); \ + } \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_fn, sizeof(CTYPENAME), aux_encfn_##DESCNAME, \ + } +/* XXX The handling of data+length fields really needs reworking. + A type descriptor probably isn't the right way. + + Also, the C type is likely to be one of char*, unsigned char*, + or (maybe) void*. An enumerator or reference to an external + function would be more compact. + + The supplied encoder function takes as an argument the data pointer + loaded from the indicated location, not the address of the field. + This isn't consistent with DEFFN[X]TYPE above, but all of the uses + of DEFFNLENTYPE are for string encodings, and that's how our + string-encoding primitives work. So be it. */ +#ifdef POINTERS_ARE_ALL_THE_SAME +#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_fn_len, 0, 0, ENCFN, \ + } +#else +#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static const void *loadptr_for_##DESCNAME(const void *pv) \ + { \ + const aux_typedefname_##DESCNAME *p = pv; \ + return *p; \ + } \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_fn_len, 0, 0, ENCFN, \ + loadptr_for_##DESCNAME \ + } +#endif +/* A sequence, defined by the indicated series of fields, and an + optional function indicating which fields are present. */ +#define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS, OPT) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static const struct seq_info aux_seqinfo_##DESCNAME = { \ + OPT, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \ + }; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_sequence, sizeof(CTYPENAME), 0,0,0,0, \ + &aux_seqinfo_##DESCNAME, \ + } +/* Integer types. */ +#define DEFINTTYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static asn1_intmax loadint_##DESCNAME(const void *p) \ + { \ + assert(sizeof(CTYPENAME) <= sizeof(asn1_intmax)); \ + return *(const aux_typedefname_##DESCNAME *)p; \ + } \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_int, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, \ + loadint_##DESCNAME, 0, \ + } +#define DEFUINTTYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static asn1_uintmax loaduint_##DESCNAME(const void *p) \ + { \ + assert(sizeof(CTYPENAME) <= sizeof(asn1_uintmax)); \ + return *(const aux_typedefname_##DESCNAME *)p; \ + } \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_uint, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, loaduint_##DESCNAME, \ + } +/* Pointers to other types, to be encoded as those other types. */ +#ifdef POINTERS_ARE_ALL_THE_SAME +#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0, 0, \ + &krb5int_asn1type_##BASEDESCNAME, 0 \ + } +#else +#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \ + static const void * \ + loadptr_for_##BASEDESCNAME##_from_##DESCNAME(const void *p) \ + { \ + const aux_typedefname_##DESCNAME *inptr = p; \ + const aux_typedefname_##BASEDESCNAME *retptr; \ + retptr = *inptr; \ + return retptr; \ + } \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0, \ + loadptr_for_##BASEDESCNAME##_from_##DESCNAME, \ + &krb5int_asn1type_##BASEDESCNAME, 0 \ + } +#endif +/* This encodes a pointer-to-pointer-to-thing where the passed-in + value points to a null-terminated list of pointers to objects to be + encoded, and encodes a (possibly empty) SEQUENCE OF these objects. + + BASEDESCNAME is a descriptor name for the pointer-to-thing + type. + + When dealing with a structure containing a + pointer-to-pointer-to-thing field, make a DEFPTRTYPE of this type, + and use that type for the structure field. */ +#define DEFNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_nullterm_sequence_of, sizeof(aux_typedefname_##DESCNAME), \ + 0, 0, \ + 0 /* loadptr */, \ + &krb5int_asn1type_##BASEDESCNAME, 0 \ + } +#define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_nonempty_nullterm_sequence_of, \ + sizeof(aux_typedefname_##DESCNAME), \ + 0, 0, \ + 0 /* loadptr */, \ + &krb5int_asn1type_##BASEDESCNAME, 0 \ + } +/* Encode a thing (probably sub-fields within the structure) as a + single object. */ +#define DEFFIELDTYPE(DESCNAME, CTYPENAME, FIELDINFO) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static const struct field_info aux_fieldinfo_##DESCNAME = FIELDINFO; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_field, sizeof(CTYPENAME), 0, 0, 0, 0, 0, \ + &aux_fieldinfo_##DESCNAME \ + } +/* Objects with an APPLICATION tag added. */ +#define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \ + typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME), \ + 0, 0, 0, &krb5int_asn1type_##BASEDESC, 0, 0, TAG, APPLICATION \ + } + +/* Declare an externally-defined type. This is a hack we should do + away with once we move to generating code from a script. For now, + this macro is unfortunately not compatible with the defining macros + above, since you can't do the typedefs twice and we need the + declarations to produce typedefs. (We could eliminate the typedefs + from the DEF* macros, but then every DEF* macro use, even the ones + for internal type nodes we only use to build other types, would + need an accompanying declaration which explicitly lists the + type.) */ +#define IMPORT_TYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + extern const struct atype_info krb5int_asn1type_##DESCNAME + +/* Create a partial-encoding function by the indicated name, for the + indicated type. Should only be needed until we've converted all of + the encoders, then everything should use descriptor tables. */ +extern asn1_error_code +krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, + const struct atype_info *a, unsigned int *retlen); +#define MAKE_ENCFN(FNAME,DESC) \ + static asn1_error_code FNAME (asn1buf *buf, \ + const aux_typedefname_##DESC *val, \ + unsigned int *retlen) \ + { \ + return krb5int_asn1_encode_a_thing(buf, val, \ + &krb5int_asn1type_##DESC, \ + retlen); \ + } \ + extern int dummy /* gobble semicolon */ + +/* Sequence field descriptor. + + Currently we assume everything is a single object with a type + descriptor, and then we bolt on some ugliness on the side for + handling strings with length fields. + + Anything with "interesting" encoding handling, like a sequence-of + or a pointer to the actual value to encode, is handled via opaque + types with their own encoder functions. Most of that should + eventually change. */ + +enum field_type { + /* Unused except for range checking. */ + field_min = 1, + /* Field ATYPE describes processing of field at DATAOFF. */ + field_normal, + /* Encode an "immediate" integer value stored in DATAOFF, with no + reference to the data structure. */ + field_immediate, + /* Encode some kind of string field encoded with pointer and + length. (A GENERALSTRING represented as a null-terminated C + string would be handled as field_normal.) */ + field_string, + /* LENOFF indicates a value describing the length of the array at + DATAOFF, encoded as a sequence-of with the element type + described by ATYPE. */ + field_sequenceof_len, + /* Unused except for range checking. */ + field_max +}; +/* To do: Consider using bitfields. */ +struct field_info { + /* Type of the field. */ + unsigned int /* enum field_type */ ftype : 3; + + /* Use of DATAOFF and LENOFF are described by the value in FTYPE. + Generally DATAOFF will be the offset from the supplied pointer + at which we find the object to be encoded. */ + unsigned int dataoff : 9, lenoff : 9; + + /* If TAG is non-negative, a context tag with that value is added + to the encoding of the thing. (XXX This would encode more + compactly as an unsigned bitfield value tagnum+1, with 0=no + tag.) The tag is omitted for optional fields that are not + present. + + It's a bit illogical to combine the tag and other field info, + since really a sequence field could have zero or several + context tags, and of course a tag could be used elsewhere. But + the normal mode in the Kerberos ASN.1 description is to use one + context tag on each sequence field, so for now let's address + that case primarily and work around the other cases (thus tag<0 + means skip tagging). */ + signed int tag : 5; + + /* If OPT is non-negative and the sequence header structure has a + function pointer describing which fields are present, OPT is + the bit position indicating whether the currently-described + element is present. (XXX Similar encoding issue.) + + Note: Most of the time, I'm using the same number here as for + the context tag. This is just because it's easier for me to + keep track while working on the code by hand. The *only* + meaningful correlation is of this value and the bits set by the + "optional" function when examining the data structure. */ + signed int opt : 5; + + /* For some values of FTYPE, this describes the type of the + object(s) to be encoded. */ + const struct atype_info *atype; + + /* We use different types for "length" fields in different places. + So we need a good way to retrieve the various kinds of lengths + in a compatible way. This may be a string length, or the + length of an array of objects to encode in a SEQUENCE OF. + + In case the field is signed and negative, or larger than + size_t, return SIZE_MAX as an error indication. We'll assume + for now that we'll never have 4G-1 (or 2**64-1, or on tiny + systems, 65535) sized values. On most if not all systems we + care about, SIZE_MAX is equivalent to "all of addressable + memory" minus one byte. That wouldn't leave enough extra room + for the structure we're encoding, so it's pretty safe to assume + SIZE_MAX won't legitimately come up on those systems. + + If this code gets ported to a segmented architecture or other + system where it might be possible... figure it out then. */ + const struct atype_info *lentype; +}; + +/* Normal or optional sequence fields at a particular offset, encoded + as indicated by the listed DESCRiptor. */ +#define FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,OPT) \ + { \ + field_normal, OFFOF(TYPE, FIELDNAME, aux_typedefname_##DESCR), \ + 0, TAG, OPT, &krb5int_asn1type_##DESCR \ + } +#define FIELDOF_NORM(TYPE,DESCR,FIELDNAME,TAG) \ + FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,-1) +/* If encoding a subset of the fields of the current structure (for + example, a flat structure describing data that gets encoded as a + sequence containing one or more sequences), use ENCODEAS, no struct + field name(s), and the indicated type descriptor must support the + current struct type. */ +#define FIELDOF_ENCODEAS(TYPE,DESCR,TAG) \ + FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,-1) +#define FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,OPT) \ + { \ + field_normal, \ + 0 * sizeof(0 ? (TYPE *)0 : (aux_typedefname_##DESCR *) 0), \ + 0, TAG, OPT, &krb5int_asn1type_##DESCR \ + } + +/* Reinterpret some subset of the structure itself as something + else. */ +#define FIELD_SELF(DESCR, TAG) \ + { field_normal, 0, 0, TAG, -1, &krb5int_asn1type_##DESCR } + +#define FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,OPT) \ + { \ + field_string, \ + OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ + OFFOF(STYPE, LENFIELD, aux_typedefname_##LENDESC), \ + TAG, OPT, &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENDESC \ + } +#define FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,OPT) \ + FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,uint,LENFIELD,TAG,OPT) +#define FIELDOF_STRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG) \ + FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,-1) +#define FIELDOF_STRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG) \ + FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,-1) +#define FIELD_INT_IMM(VALUE,TAG) \ + { field_immediate, VALUE, 0, TAG, -1, 0, } + +#define FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG) \ + { \ + field_sequenceof_len, \ + OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ + OFFOF(STYPE, LENFIELD, aux_typedefname_##LENTYPE), \ + TAG, -1, &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \ + } +#define FIELDOF_SEQOF_INT32(STYPE,DESC,PTRFIELD,LENFIELD,TAG) \ + FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,int32,TAG) + +struct seq_info { + /* If present, returns a bitmask indicating which fields are + present. See the "opt" field in struct field_info. */ + unsigned int (*optional)(const void *); + /* Indicates an array of sequence field descriptors. */ + const struct field_info *fields; + size_t n_fields; + /* Missing: Extensibility handling. (New field type?) */ +}; + +extern krb5_error_code +krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, + const struct atype_info *a); + +#define MAKE_FULL_ENCODER(FNAME, DESC) \ + krb5_error_code FNAME(const aux_typedefname_##DESC *rep, \ + krb5_data **code) \ + { \ + return krb5int_asn1_do_full_encode(rep, code, \ + &krb5int_asn1type_##DESC); \ + } \ + extern int dummy /* gobble semicolon */ + +#include +/* Ugly hack! + Like "offsetof", but with type checking. */ +#define WARN_IF_TYPE_MISMATCH(LVALUE, TYPE) \ + (sizeof(0 ? (TYPE *) 0 : &(LVALUE))) +#define OFFOF(TYPE,FIELD,FTYPE) \ + (offsetof(TYPE, FIELD) \ + + 0 * WARN_IF_TYPE_MISMATCH(((TYPE*)0)->FIELD, FTYPE)) + +#endif diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_get.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_get.c new file mode 100644 index 000000000..d3706fbd6 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_get.c @@ -0,0 +1,119 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/krb5/asn.1/asn1_get.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_get.h new file mode 100644 index 000000000..ecafa2aec --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_get.h @@ -0,0 +1,85 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 { +#if 1 /* Smaller run-time storage, and on x86 the compiler can use + byte loads, stores, and compares, but on other platforms the + compiler may need to load and widen before comparing... see + how this works out. */ + unsigned int asn1class : 8, construction : 8; +#else + asn1_class asn1class; + asn1_construction construction; +#endif + 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-7/src/lib/krb5/asn.1/asn1_k_decode.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.c new file mode 100644 index 000000000..f672c1609 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.c @@ -0,0 +1,2359 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/asn1_k_decode.c + * + * Copyright 1994, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" + +#define clean_return(val) { retval = val; goto error_out; } + +/* 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) clean_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; \ +} + +static asn1_error_code +asn1_get_eoc_tag (asn1buf *buf) +{ + asn1_error_code retval; + taginfo t; + + retval = asn1_get_tag_2(buf, &t); + if (retval) + return retval; + if (t.asn1class != UNIVERSAL || t.tagnum || t.indef) + return ASN1_MISSING_EOC; + return 0; +} + +/* Force check for EOC tag. */ +#define get_eoc() \ + { \ + retval = asn1_get_eoc_tag(&subbuf); \ + if (retval) clean_return(retval); \ + } + +#define alloc_field(var) \ + var = calloc(1, sizeof(*var)); \ + if ((var) == NULL) clean_return(ENOMEM) + +/* + * Allocate a principal and initialize enough fields for + * krb5_free_principal to have defined behavior. + */ +#define alloc_principal(var) \ + alloc_field(var); \ + var->realm.data = NULL; \ + var->data = NULL + +/* + * Allocate a data structure and initialize enough fields for + * krb5_free_data to have defined behavior. + */ +#define alloc_data(var) \ + alloc_field(var); \ + var->data = NULL + +/* Fetch an expected APPLICATION class tag and verify. */ +#define apptag(tagexpect) \ + { \ + taginfo t1; \ + retval = asn1_get_tag_2(buf, &t1); \ + if (retval) clean_return(retval); \ + if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED || \ + t1.tagnum != (tagexpect)) clean_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) clean_return(retval); \ + if (!taglen && indef) { get_eoc(); } \ + next_tag() + +/* + * error_if_bad_tag + * + * Checks that the next tag is the expected one; returns with an error + * if not. + */ +#define error_if_bad_tag(tagexpect) \ + if (tagnum != (tagexpect)) { clean_return((tagnum < (tagexpect)) ? ASN1_MISPLACED_FIELD : ASN1_MISSING_FIELD); } + +/* + * 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) \ + error_if_bad_tag(tagexpect); \ + if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ + && (tagnum || taglen || asn1class != UNIVERSAL)) \ + clean_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)) \ + clean_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) clean_return(retval); \ + if (!taglen && indef) { get_eoc(); } \ + next_tag() + +/* similar to get_field_body */ +#define get_lenfield(len, var, tagexpect, decoder) \ + error_if_bad_tag(tagexpect); \ + if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ + && (tagnum || taglen || asn1class != UNIVERSAL)) \ + clean_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)) clean_return(ASN1_MISSING_FIELD); \ + if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ + clean_return(ASN1_BAD_ID); \ + retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ + if (retval) clean_return(retval); \ + (len) = taglen; \ + next_tag() + +#define opt_implicit_octet_string(len, var, tagexpect) \ + if (tagnum == (tagexpect)) { \ + if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ + clean_return(ASN1_BAD_ID); \ + retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ + if (retval) clean_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) clean_return(retval); \ + retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ + if (retval) clean_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) clean_return(retval); \ + retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ + if (retval) clean_return(retval) + +/* skip trailing garbage */ +#define end_structure() \ + retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum, \ + length, indef, seqindef); \ + if (retval) clean_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) clean_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) clean_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) clean_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) \ + 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) \ + asn1buf seqbuf; \ + int seqofindef; \ + retval = asn1_get_sequence(buf, &length, &seqofindef); \ + if (retval) clean_return(retval); \ + retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef); \ + if (retval) clean_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) clean_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) clean_return(retval); + +/* + * end_sequence_of_no_tagvars + * + * Like end_sequence_of(), but uses the different (non-shadowing) + * variable names. + */ +static asn1_error_code +end_sequence_of_no_tagvars_helper(asn1buf *buf, asn1buf *seqbufp, + int seqofindef) +{ + taginfo t; + asn1_error_code retval; + + retval = asn1_get_tag_2(seqbufp, &t); + if (retval) + return retval; + retval = asn1buf_sync(buf, seqbufp, t.asn1class, t.tagnum, + t.length, t.indef, seqofindef); + return retval; +} +#define end_sequence_of_no_tagvars(buf) \ + retval = end_sequence_of_no_tagvars_helper(buf, &seqbuf, seqofindef); \ + if (retval) clean_return(retval) + +/* + * Function body for a pointer decoder, which allocates a pointer + * field and invokes a structure decoder to fill it in. Pointer + * decoders always fill in their output parameters with NULL (on + * error) or a valid constructed structure, making cleanup easier on + * callers. + */ +#define decode_ptr(type, structure_decoder) \ + type val; \ + asn1_error_code retval; \ +\ + *valptr = NULL; \ + val = calloc(1, sizeof(*val)); \ + if (!val) \ + return ENOMEM; \ + retval = structure_decoder(buf, val); \ + if (retval) { \ + free(val); \ + return retval; \ + } \ + *valptr = val; \ + 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) +{ + int size = 0, i; + krb5_data *array = NULL, *new_array; + + setup(); + { begin_structure(); + get_field((*val)->type,0,asn1_decode_int32); + + { sequence_of_no_tagvars(&subbuf); + while (asn1buf_remains(&seqbuf,seqofindef) > 0) { + unsigned int len; + char *str; + + new_array = realloc(array, (size + 1) * sizeof(krb5_data)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_decode_generalstring(&seqbuf, &len, &str); + if (retval) clean_return(retval); + array[size].data = str; + array[size].length = len; + size++; + } + end_sequence_of_no_tagvars(&subbuf); + } + if (indef) { + get_eoc(); + } + next_tag(); + end_structure(); + } + (*val)->data = array; + (*val)->length = size; + (*val)->magic = KV5M_PRINCIPAL; + return 0; +error_out: + for (i = 0; i < size; i++) + free(array[i].data); + free(array); + return retval; +} + +asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val) +{ + setup(); + val->contents = NULL; + { 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; + } + return 0; +error_out: + free(val->contents); + return retval; +} + +asn1_error_code asn1_decode_checksum_ptr(asn1buf *buf, krb5_checksum **valptr) +{ + decode_ptr(krb5_checksum *, asn1_decode_checksum); +} + +asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val) +{ + setup(); + val->contents = NULL; + { 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; + } + return 0; +error_out: + free(val->contents); + return retval; +} + +asn1_error_code +asn1_decode_encryption_key_ptr(asn1buf *buf, krb5_keyblock **valptr) +{ + decode_ptr(krb5_keyblock *, asn1_decode_encryption_key); +} + +asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val) +{ + setup(); + val->ciphertext.data = NULL; + { 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; + } + return 0; +error_out: + free(val->ciphertext.data); + val->ciphertext.data = NULL; + return retval; +} + +asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val) +{ + asn1_error_code retval; + asn1_octet unused, o; + taginfo t; + unsigned 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(); + val->tr_contents.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_data_contents(NULL, &val->tr_contents); + return retval; +} + +asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val) +{ + setup(); + val->session = NULL; + val->last_req = NULL; + val->server = NULL; + val->caddrs = NULL; + { begin_structure(); + get_field(val->session,0,asn1_decode_encryption_key_ptr); + 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_principal(val->server); + 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); + opt_field(val->enc_padata,12,asn1_decode_sequence_of_pa_data,NULL); + end_structure(); + val->magic = KV5M_ENC_KDC_REP_PART; + } + return 0; +error_out: + krb5_free_keyblock(NULL, val->session); + krb5_free_last_req(NULL, val->last_req); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + krb5_free_pa_data(NULL, val->enc_padata); + val->session = NULL; + val->last_req = NULL; + val->server = NULL; + val->caddrs = NULL; + return retval; +} + +asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val) +{ + setup(); + unsigned int applen; + apptag(1); + val->server = NULL; + val->enc_part.ciphertext.data = NULL; + val->enc_part2 = NULL; + { begin_structure(); + { krb5_kvno vno; + get_field(vno,0,asn1_decode_kvno); + if (vno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } + alloc_principal(val->server); + 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) clean_return(retval); + } + return 0; +error_out: + krb5_free_principal(NULL, val->server); + krb5_free_data_contents(NULL, &val->enc_part.ciphertext); + val->server = NULL; + return retval; +} + +asn1_error_code +asn1_decode_ticket_ptr(asn1buf *buf, krb5_ticket **valptr) +{ + decode_ptr(krb5_ticket *, asn1_decode_ticket); +} + +asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val) +{ + setup(); + val->padata = NULL; + { begin_structure(); + { krb5_kvno kvno; + get_field(kvno,1,asn1_decode_kvno); + if (kvno != KVNO) clean_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; + } + return 0; +error_out: + krb5_free_pa_data(NULL, val->padata); + val->padata = NULL; + return retval; +} + +asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val) +{ + setup(); + val->client = NULL; + val->server = NULL; + val->ktype = NULL; + val->addresses = NULL; + val->authorization_data.ciphertext.data = NULL; + val->unenc_authdata = NULL; + val->second_ticket = NULL; + { + krb5_principal psave; + begin_structure(); + get_field(val->kdc_options,0,asn1_decode_kdc_options); + if (tagnum == 1) { alloc_principal(val->client); } + opt_field(val->client,1,asn1_decode_principal_name,NULL); + alloc_principal(val->server); + get_field(val->server,2,asn1_decode_realm); + if (val->client != NULL) { + retval = asn1_krb5_realm_copy(val->client,val->server); + if (retval) clean_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; + } + return 0; +error_out: + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + free(val->ktype); + krb5_free_addresses(NULL, val->addresses); + krb5_free_data_contents(NULL, &val->authorization_data.ciphertext); + krb5_free_tickets(NULL, val->second_ticket); + val->client = NULL; + val->server = NULL; + val->ktype = NULL; + val->addresses = NULL; + val->unenc_authdata = NULL; + val->second_ticket = NULL; + return retval; +} + +asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val) +{ + setup(); + val->user_data.data = NULL; + val->r_address = NULL; + val->s_address = NULL; + val->checksum = NULL; + { 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); + get_field(val->s_address,4,asn1_decode_host_address_ptr); + if (tagnum == 5) { + get_field(val->r_address,5,asn1_decode_host_address_ptr); + } + end_structure(); + val->magic = KV5M_SAFE; + } + return 0; +error_out: + krb5_free_data_contents(NULL, &val->user_data); + krb5_free_address(NULL, val->r_address); + krb5_free_address(NULL, val->s_address); + val->r_address = NULL; + val->s_address = NULL; + return retval; +} + +asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val) +{ + setup(); + val->contents = NULL; + { 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; + } + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code +asn1_decode_host_address_ptr(asn1buf *buf, krb5_address **valptr) +{ + decode_ptr(krb5_address *, asn1_decode_host_address); +} + +asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val) +{ + setup(); + val->padata = NULL; + val->client = NULL; + val->ticket = NULL; + val->enc_part.ciphertext.data = NULL; + val->enc_part2 = NULL; + { begin_structure(); + { krb5_kvno pvno; + get_field(pvno,0,asn1_decode_kvno); + if (pvno != KVNO) clean_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_principal(val->client); + get_field(val->client,3,asn1_decode_realm); + get_field(val->client,4,asn1_decode_principal_name); + get_field(val->ticket,5,asn1_decode_ticket_ptr); + get_field(val->enc_part,6,asn1_decode_encrypted_data); + end_structure(); + val->magic = KV5M_KDC_REP; + } + return 0; +error_out: + krb5_free_pa_data(NULL, val->padata); + krb5_free_principal(NULL, val->client); + krb5_free_ticket(NULL, val->ticket); + krb5_free_data_contents(NULL, &val->enc_part.ciphertext); + val->padata = NULL; + val->client = NULL; + val->ticket = NULL; + val->enc_part.ciphertext.data = NULL; + return retval; +} + + +/* arrays */ +#define get_element(element,decoder)\ +retval = decoder(&seqbuf,&element);\ +if (retval) clean_return(retval) + +static void * +array_expand (void *array, int n_elts, size_t elt_size) +{ + size_t new_size; + + if (n_elts <= 0) + return NULL; + if ((unsigned int) n_elts > SIZE_MAX / elt_size) + return NULL; + new_size = n_elts * elt_size; + if (new_size == 0) + return NULL; + if (new_size / elt_size != (unsigned int) n_elts) + return NULL; + return realloc(array, new_size); +} + +#define array_append(array,size,element,type)\ + {\ + void *new_array = array_expand(*(array), (size)+2, sizeof(type*));\ + if (new_array == NULL) clean_return(ENOMEM);\ + *(array) = new_array;\ + (*(array))[(size)++] = elt;\ + } + +/* + * Function body for array decoders. freefn is expected to look like + * a krb5_free_ function, so we pass a null first argument. + */ +#define decode_array_body(type,decoder,freefn)\ + asn1_error_code retval;\ + type *elt = NULL, **array;\ + int size = 0, i; \ +\ + array = *val = NULL;\ + { sequence_of(buf);\ + while (asn1buf_remains(&seqbuf,seqofindef) > 0) {\ + get_element(elt,decoder);\ + array_append(&array,size,elt,type);\ + elt = NULL;\ + }\ + if (array == NULL)\ + array = malloc(sizeof(type*));\ + array[size] = NULL;\ + end_sequence_of(buf);\ + }\ + *val = array;\ + return 0;\ +error_out:\ + if (elt)\ + freefn(NULL,elt);\ + for (i = 0; i < size; i++)\ + freefn(NULL,array[i]);\ + free(array);\ + return retval + +static void free_authdata_elt(void *dummy, krb5_authdata *val) +{ + free(val->contents); + free(val); +} + +asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val) +{ + decode_array_body(krb5_authdata,asn1_decode_authdata_elt_ptr, + free_authdata_elt); +} + +asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val) +{ + setup(); + val->contents = NULL; + { 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; + } + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code +asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr) +{ + decode_ptr(krb5_authdata *, asn1_decode_authdata_elt); +} + +asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val) +{ + decode_array_body(krb5_address,asn1_decode_host_address_ptr, + krb5_free_address); +} + +asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val) +{ + decode_array_body(krb5_ticket,asn1_decode_ticket_ptr,krb5_free_ticket); +} + +static void free_cred_info(void *dummy, krb5_cred_info *val) +{ + krb5_free_keyblock(NULL, val->session); + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + free(val); +} + +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_ptr, + free_cred_info); +} + +asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val) +{ + setup(); + val->session = NULL; + val->client = NULL; + val->server = NULL; + val->caddrs = NULL; + { begin_structure(); + get_field(val->session,0,asn1_decode_encryption_key_ptr); + if (tagnum == 1) { + alloc_principal(val->client); + 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_principal(val->server); + 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; + } + return 0; +error_out: + krb5_free_keyblock(NULL, val->session); + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + val->session = NULL; + val->client = NULL; + val->server = NULL; + val->caddrs = NULL; + return retval; +} + +asn1_error_code +asn1_decode_krb_cred_info_ptr(asn1buf *buf, krb5_cred_info **valptr) +{ + decode_ptr(krb5_cred_info *, asn1_decode_krb_cred_info); +} + +static void free_pa_data(void *dummy, krb5_pa_data *val) +{ + free(val->contents); + free(val); +} + +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_ptr,free_pa_data); +} + +asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val) +{ + setup(); + val->contents = NULL; + { 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; + } + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code asn1_decode_pa_data_ptr(asn1buf *buf, krb5_pa_data **valptr) +{ + decode_ptr(krb5_pa_data *, asn1_decode_pa_data); +} + +static void free_last_req_entry(void *dummy, krb5_last_req_entry *val) +{ + free(val); +} + +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_ptr, + free_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 + } + return 0; +error_out: + return retval; +} + +asn1_error_code +asn1_decode_last_req_entry_ptr(asn1buf *buf, krb5_last_req_entry **valptr) +{ + decode_ptr(krb5_last_req_entry *, asn1_decode_last_req_entry); +} + +asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val) +{ + int size = 0; + krb5_enctype *array = NULL, *new_array; + + asn1_error_code retval; + { sequence_of(buf); + while (asn1buf_remains(&seqbuf,seqofindef) > 0) { + size++; + new_array = realloc(array,size*sizeof(krb5_enctype)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_decode_enctype(&seqbuf,&array[size-1]); + if (retval) clean_return(retval); + } + end_sequence_of(buf); + } + *num = size; + *val = array; + return 0; +error_out: + free(array); + return retval; +} + +asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val) +{ + decode_array_body(krb5_checksum, asn1_decode_checksum_ptr, + krb5_free_checksum); +} + +static void free_etype_info_entry(void *dummy, krb5_etype_info_entry *val) +{ + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + free(val); +} + +static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val ) +{ + char *salt = NULL; + krb5_octet *params = NULL; + setup(); + val->salt = NULL; + val->s2kparams.data = NULL; + { begin_structure(); + get_field(val->etype,0,asn1_decode_enctype); + if (tagnum == 1) { + get_lenfield(val->length,salt,1,asn1_decode_generalstring); + val->salt = (krb5_octet *) salt; + salt = NULL; + } else + val->length = KRB5_ETYPE_NO_SALT; + if ( tagnum ==2) { + get_lenfield( val->s2kparams.length, params, + 2, asn1_decode_octetstring); + val->s2kparams.data = ( char *) params; + params = NULL; + } else + val->s2kparams.length = 0; + end_structure(); + val->magic = KV5M_ETYPE_INFO_ENTRY; + } + return 0; +error_out: + free(salt); + free(params); + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + val->salt = NULL; + return retval; +} + +static asn1_error_code +asn1_decode_etype_info2_entry_ptr(asn1buf *buf, krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info2_entry); +} + +static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val ) +{ + setup(); + val->salt = NULL; + val->s2kparams.data = NULL; + { 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; + if ( tagnum ==2) { + krb5_octet *params ; + get_lenfield( val->s2kparams.length, params, + 2, asn1_decode_octetstring); + val->s2kparams.data = ( char *) params; + } else + val->s2kparams.length = 0; + end_structure(); + val->magic = KV5M_ETYPE_INFO_ENTRY; + } + return 0; +error_out: + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + val->salt = NULL; + return retval; +} + +static asn1_error_code +asn1_decode_etype_info2_entry_1_3_ptr(asn1buf *buf, + krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info2_entry_1_3); +} + +static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val ) +{ + setup(); + val->salt = NULL; + val->s2kparams.data = NULL; + { 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->s2kparams.length = 0; + + end_structure(); + val->magic = KV5M_ETYPE_INFO_ENTRY; + } + return 0; +error_out: + free(val->salt); + val->salt = NULL; + return retval; +} + +static asn1_error_code +asn1_decode_etype_info_entry_ptr(asn1buf *buf, krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info_entry); +} + +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_ptr, + free_etype_info_entry); +} + +static asn1_error_code decode_etype_info2_13(asn1buf *buf, krb5_etype_info_entry ***val) +{ + decode_array_body(krb5_etype_info_entry, + asn1_decode_etype_info2_entry_1_3_ptr, + free_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) + return decode_etype_info2_13(buf, val); + else { + decode_array_body(krb5_etype_info_entry, + asn1_decode_etype_info2_entry_ptr, + free_etype_info_entry); + } +} + +asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val) +{ + setup(); + val->passwd = NULL; + val->phrase = NULL; + { begin_structure(); + alloc_data(val->passwd); + get_lenfield(val->passwd->length,val->passwd->data, + 0,asn1_decode_charstring); + val->passwd->magic = KV5M_DATA; + alloc_data(val->phrase); + 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; + } + return 0; +error_out: + krb5_free_data(NULL, val->passwd); + krb5_free_data(NULL, val->phrase); + val->passwd = NULL; + val->phrase = NULL; + return 0; +} + +asn1_error_code +asn1_decode_passwdsequence_ptr(asn1buf *buf, passwd_phrase_element **valptr) +{ + decode_ptr(passwd_phrase_element *, asn1_decode_passwdsequence); +} + +asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val) +{ + decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence_ptr, + krb5_free_passwd_phrase_element); +} + +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(); + val->sam_type_name.data = NULL; + val->sam_track_id.data = NULL; + val->sam_challenge_label.data = NULL; + val->sam_response_prompt.data = NULL; + val->sam_pk_for_sad.data = NULL; + val->sam_cksum.contents = NULL; + { 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; + } + return 0; +error_out: + krb5_free_sam_challenge_contents(NULL, val); + return retval; +} +asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val) +{ + krb5_checksum **cksump; + setup(); + val->sam_challenge_2_body.data = NULL; + val->sam_cksum = NULL; + { char *save, *end; + size_t alloclen; + begin_structure(); + if (tagnum != 0) clean_return(ASN1_MISSING_FIELD); + if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) + clean_return(ASN1_BAD_ID); + save = subbuf.next; + { sequence_of_no_tagvars(&subbuf); + end_sequence_of_no_tagvars(&subbuf); + } + end = subbuf.next; + alloclen = end - save; + val->sam_challenge_2_body.data = malloc(alloclen); + if (!val->sam_challenge_2_body.data) + clean_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(); + } + return 0; +error_out: + krb5_free_data_contents(NULL, &val->sam_challenge_2_body); + if (val->sam_cksum) { + for (cksump = val->sam_cksum; *cksump; cksump++) + krb5_free_checksum(NULL, *cksump); + free(val->sam_cksum); + val->sam_cksum = NULL; + } + return retval; +} +asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val) +{ + setup(); + val->sam_type_name.data = NULL; + val->sam_track_id.data = NULL; + val->sam_challenge_label.data = NULL; + val->sam_challenge.data = NULL; + val->sam_response_prompt.data = NULL; + val->sam_pk_for_sad.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_sam_challenge_2_body_contents(NULL, val); + return retval; +} +asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val) +{ + setup(); + val->sam_key.contents = NULL; + { begin_structure(); + get_field(val->sam_key,0,asn1_decode_encryption_key); + end_structure(); + val->magic = KV5M_SAM_KEY; + } + return 0; +error_out: + krb5_free_keyblock_contents(NULL, &val->sam_key); + return retval; +} + +asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val) +{ + setup(); + val->sam_sad.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_enc_sam_response_enc_contents(NULL, val); + return retval; +} + +asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val) +{ + setup(); + val->sam_sad.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_enc_sam_response_enc_2_contents(NULL, val); + return retval; +} + +#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(); + val->sam_track_id.data = NULL; + val->sam_enc_key.ciphertext.data = NULL; + val->sam_enc_nonce_or_ts.ciphertext.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_sam_response_contents(NULL, val); + return retval; +} + +asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val) +{ + setup(); + val->sam_track_id.data = NULL; + val->sam_enc_nonce_or_sad.ciphertext.data = NULL; + { 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; + } + return 0; +error_out: + krb5_free_sam_response_2_contents(NULL, val); + return retval; +} + + +asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val) +{ + setup(); + val->sam_key.contents = NULL; + val->client = NULL; + val->msd.data = NULL; + { 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_principal(val->client); + 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; + } + return 0; +error_out: + krb5_free_predicted_sam_response_contents(NULL, val); + return retval; +} + +asn1_error_code asn1_decode_setpw_req(asn1buf *buf, krb5_data *newpasswd, krb5_principal *principal) +{ + krb5_principal princ = NULL; + setup(); + *principal = NULL; + + newpasswd->data = NULL; + { begin_structure(); + get_lenfield(newpasswd->length, newpasswd->data, 0, asn1_decode_charstring); + if (tagnum == 1) { + alloc_principal(princ); + opt_field(princ, 1, asn1_decode_principal_name, 0); + opt_field(princ, 2, asn1_decode_realm, 0); + } + end_structure(); + } + *principal = princ; + return 0; +error_out: + krb5_free_data_contents(NULL, newpasswd); + krb5_free_principal(NULL, princ); + return retval; +} + +asn1_error_code asn1_decode_pa_for_user(asn1buf *buf, krb5_pa_for_user *val) +{ + setup(); + val->user = NULL; + val->cksum.contents = NULL; + val->auth_package.data = NULL; + { begin_structure(); + alloc_principal(val->user); + get_field(val->user,0,asn1_decode_principal_name); + get_field(val->user,1,asn1_decode_realm); + get_field(val->cksum,2,asn1_decode_checksum); + get_lenfield(val->auth_package.length,val->auth_package.data,3,asn1_decode_generalstring); + end_structure(); + } + return 0; +error_out: + krb5_free_principal(NULL, val->user); + krb5_free_checksum_contents(NULL, &val->cksum); + krb5_free_data_contents(NULL, &val->auth_package); + val->user = NULL; + return retval; +} + +asn1_error_code asn1_decode_pa_pac_req(asn1buf *buf, krb5_pa_pac_req *val) +{ + setup(); + { begin_structure(); + get_field(val->include_pac,0,asn1_decode_boolean); + end_structure(); + } + return 0; +error_out: + return retval; +} + +asn1_error_code asn1_decode_fast_armor +(asn1buf *buf, krb5_fast_armor *val) +{ + setup(); + val->armor_value.data = NULL; + {begin_structure(); + get_field(val->armor_type, 0, asn1_decode_int32); + get_lenfield(val->armor_value.length, val->armor_value.data, + 1, asn1_decode_charstring); + end_structure(); + } + return 0; + error_out: + krb5_free_data_contents( NULL, &val->armor_value); + return retval; +} + +asn1_error_code asn1_decode_fast_armor_ptr +(asn1buf *buf, krb5_fast_armor **valptr) +{ + decode_ptr(krb5_fast_armor *, asn1_decode_fast_armor); +} + +asn1_error_code asn1_decode_fast_finished +(asn1buf *buf, krb5_fast_finished *val) +{ + setup(); + val->client = NULL; + val->ticket_checksum.contents = NULL; + {begin_structure(); + get_field(val->timestamp, 0, asn1_decode_kerberos_time); + get_field(val->usec, 1, asn1_decode_int32); + alloc_field(val->client); + get_field(val->client, 2, asn1_decode_realm); + get_field(val->client, 3, asn1_decode_principal_name); + get_field(val->ticket_checksum, 4, asn1_decode_checksum); + end_structure(); + } + return 0; + error_out: + krb5_free_principal(NULL, val->client); + krb5_free_checksum_contents( NULL, &val->ticket_checksum); + return retval; +} +asn1_error_code asn1_decode_fast_finished_ptr +(asn1buf *buf, krb5_fast_finished **valptr) +{ + decode_ptr( krb5_fast_finished *, asn1_decode_fast_finished); +} + + +#ifndef DISABLE_PKINIT +/* PKINIT */ + +asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val) +{ + setup(); + val->subjectName.data = NULL; + val->issuerAndSerialNumber.data = NULL; + val->subjectKeyIdentifier.data = NULL; + { + 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(); + } + return 0; +error_out: + free(val->subjectName.data); + free(val->issuerAndSerialNumber.data); + free(val->subjectKeyIdentifier.data); + val->subjectName.data = NULL; + val->issuerAndSerialNumber.data = NULL; + val->subjectKeyIdentifier.data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_external_principal_identifier_ptr + (asn1buf *buf, + krb5_external_principal_identifier **valptr) +{ + decode_ptr(krb5_external_principal_identifier *, + asn1_decode_external_principal_identifier); +} + +static void +free_external_principal_identifier(void *dummy, + krb5_external_principal_identifier *val) +{ + free(val->subjectName.data); + free(val->issuerAndSerialNumber.data); + free(val->subjectKeyIdentifier.data); + free(val); +} + +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_ptr, + free_external_principal_identifier); +} + +asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val) +{ + setup(); + val->signedAuthPack.data = NULL; + val->trustedCertifiers = NULL; + val->kdcPkId.data = NULL; + { + 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(); + } + return 0; +error_out: + free(val->signedAuthPack.data); + free(val->trustedCertifiers); + free(val->kdcPkId.data); + val->signedAuthPack.data = NULL; + val->trustedCertifiers = NULL; + val->kdcPkId.data = NULL; + return retval; +} + +#if 0 /* XXX This needs to be tested!!! XXX */ +asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) +{ + setup(); + val->choice = choice_trusted_cas_UNKNOWN; + { + 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; + val->u.caName.data = NULL; + 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) + clean_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; + val->u.issuerAndSerial.data = NULL; + 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) + clean_return(ENOMEM); + memcpy(val->u.issuerAndSerial.data, start, alloclen); + val->u.issuerAndSerial.length = alloclen; + next_tag(); + } else clean_return(ASN1_BAD_ID); + end_explicit_choice(); + } + return 0; +error_out: + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + val->choice = choice_trusted_cas_UNKNOWN; + return retval; +} +#else +asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) +{ + setup(); + val->choice = choice_trusted_cas_UNKNOWN; + { begin_choice(); + if (tagnum == choice_trusted_cas_principalName) { + val->choice = choice_trusted_cas_principalName; + val->u.principalName = NULL; + asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName)); + } else if (tagnum == choice_trusted_cas_caName) { + val->choice = choice_trusted_cas_caName; + val->u.caName.data = NULL; + 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; + val->u.issuerAndSerial.data = NULL; + get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data, + choice_trusted_cas_issuerAndSerial); + } else clean_return(ASN1_BAD_ID); + end_choice(); + } + return 0; +error_out: + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + val->choice = choice_trusted_cas_UNKNOWN; + return retval; +} +#endif + +asn1_error_code +asn1_decode_trusted_ca_ptr(asn1buf *buf, krb5_trusted_ca **valptr) +{ + decode_ptr(krb5_trusted_ca *, asn1_decode_trusted_ca); +} + +static void free_trusted_ca(void *dummy, krb5_trusted_ca *val) +{ + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + free(val); +} + +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_ptr, + free_trusted_ca); +} + +asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val) +{ + int i; + setup(); + val->signedAuthPack.data = NULL; + val->kdcCert.data = NULL; + val->encryptionCert.data = NULL; + val->trustedCertifiers = NULL; + { 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(); + } + return 0; +error_out: + free(val->signedAuthPack.data); + free(val->kdcCert.data); + free(val->encryptionCert.data); + if (val->trustedCertifiers) { + for (i = 0; val->trustedCertifiers[i]; i++) + free_trusted_ca(NULL, val->trustedCertifiers[i]); + free(val->trustedCertifiers); + } + val->signedAuthPack.data = NULL; + val->kdcCert.data = NULL; + val->encryptionCert.data = NULL; + val->trustedCertifiers = NULL; + return retval; +} + +asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val) +{ + setup(); + val->dhSignedData.data = NULL; + val->serverDHNonce.data = NULL; + { 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(); + } + return 0; +error_out: + free(val->dhSignedData.data); + free(val->serverDHNonce.data); + val->dhSignedData.data = NULL; + val->serverDHNonce.data = NULL; + return retval; +} + +asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val) +{ + setup(); + val->paChecksum.contents = NULL; + { 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(); + } + return 0; +error_out: + krb5_free_checksum_contents(NULL, &val->paChecksum); + return retval; +} + +asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val) +{ + setup(); + val->kdcName = NULL; + val->kdcRealm.data = NULL; + { begin_structure(); + alloc_principal(val->kdcName); + 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(); + } + return 0; +error_out: + krb5_free_principal(NULL, val->kdcName); + return retval; +} + +asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier *val) { + + setup(); + val->algorithm.data = NULL; + val->parameters.data = NULL; + { 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) clean_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) clean_return(retval); + val->parameters.length = 0; + val->parameters.data = NULL; + + assert(subbuf.next >= subbuf.base); + if (length > (size_t)(subbuf.next - subbuf.base)) { + unsigned int size = length - (subbuf.next - subbuf.base); + retval = asn1buf_remove_octetstring(&subbuf, size, + &val->parameters.data); + if (retval) clean_return(retval); + val->parameters.length = size; + } + + end_structure(); + } + return 0; +error_out: + free(val->algorithm.data); + free(val->parameters.data); + val->algorithm.data = NULL; + val->parameters.data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_algorithm_identifier_ptr(asn1buf *buf, + krb5_algorithm_identifier **valptr) +{ + decode_ptr(krb5_algorithm_identifier *, asn1_decode_algorithm_identifier); +} + +asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val) +{ + asn1_octet unused; + setup(); + val->algorithm.algorithm.data = NULL; + val->algorithm.parameters.data = NULL; + val->subjectPublicKey.data = NULL; + { begin_structure_no_tag(); + + retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm); + if (retval) clean_return(retval); + + /* SubjectPublicKey encoded as a BIT STRING */ + next_tag(); + if (asn1class != UNIVERSAL || construction != PRIMITIVE || + tagnum != ASN1_BITSTRING) + clean_return(ASN1_BAD_ID); + + retval = asn1buf_remove_octet(&subbuf, &unused); + if (retval) clean_return(retval); + + /* Number of unused bits must be between 0 and 7. */ + /* What to do if unused is not zero? */ + if (unused > 7) clean_return(ASN1_BAD_FORMAT); + taglen--; + + val->subjectPublicKey.length = 0; + val->subjectPublicKey.data = NULL; + retval = asn1buf_remove_octetstring(&subbuf, taglen, + &val->subjectPublicKey.data); + if (retval) clean_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(); + } + return 0; +error_out: + free(val->algorithm.algorithm.data); + free(val->algorithm.parameters.data); + free(val->subjectPublicKey.data); + val->algorithm.algorithm.data = NULL; + val->algorithm.parameters.data = NULL; + val->subjectPublicKey.data = NULL; + return 0; +} + +static void +free_algorithm_identifier(void *dummy, krb5_algorithm_identifier *val) +{ + free(val->algorithm.data); + free(val->parameters.data); + free(val); +} + +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_ptr, + free_algorithm_identifier); +} + +asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val) +{ + setup(); + val->subjectPublicKey.data = NULL; + { begin_structure(); + retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data); + if (retval) clean_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(); + } + return 0; +error_out: + free(val->subjectPublicKey.data); + val->subjectPublicKey.data = NULL; + return retval; +} + +asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val) +{ + setup(); + val->replyKey.contents = NULL; + val->asChecksum.contents = NULL; + { begin_structure(); + get_field(val->replyKey, 0, asn1_decode_encryption_key); + get_field(val->asChecksum, 1, asn1_decode_checksum); + end_structure(); + } + return 0; +error_out: + free(val->replyKey.contents); + free(val->asChecksum.contents); + val->replyKey.contents = NULL; + val->asChecksum.contents = NULL; + return retval; +} + +asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val) +{ + setup(); + val->replyKey.contents = NULL; + { begin_structure(); + get_field(val->replyKey, 0, asn1_decode_encryption_key); + get_field(val->nonce, 1, asn1_decode_int32); + end_structure(); + } + return 0; +error_out: + free(val->replyKey.contents); + val->replyKey.contents = NULL; + return retval; +} + + +asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val) +{ + int i; + setup(); + (*val)->realm.data = NULL; + (*val)->data = NULL; + { begin_structure(); + get_field(*val, 0, asn1_decode_realm); + get_field(*val, 1, asn1_decode_principal_name); + end_structure(); + } + return 0; +error_out: + krb5_free_data_contents(NULL, &(*val)->realm); + if ((*val)->data) { + for (i = 0; i < (*val)->length; i++) + krb5_free_data_contents(NULL, &(*val)->data[i]); + free((*val)->data); + } + (*val)->realm.data = NULL; + (*val)->data = NULL; + return retval; +} + +asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) +{ + int i; + setup(); + val->clientPublicValue = NULL; + val->pkAuthenticator.paChecksum.contents = NULL; + val->supportedCMSTypes = NULL; + val->clientDHNonce.data = NULL; + { begin_structure(); + get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator); + if (tagnum == 1) { + alloc_field(val->clientPublicValue); + val->clientPublicValue->algorithm.algorithm.data = NULL; + val->clientPublicValue->algorithm.parameters.data = NULL; + val->clientPublicValue->subjectPublicKey.data = NULL; + } + /* 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)) + clean_return(ASN1_BAD_ID); + if (tagnum == 1) { + retval = asn1_decode_subject_pk_info(&subbuf, + val->clientPublicValue); + if (retval) clean_return(retval); + 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) { + retval = asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes); + if (retval) clean_return(retval); + 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(); + } + return 0; +error_out: + if (val->clientPublicValue) { + free(val->clientPublicValue->algorithm.algorithm.data); + free(val->clientPublicValue->algorithm.parameters.data); + free(val->clientPublicValue->subjectPublicKey.data); + free(val->clientPublicValue); + } + free(val->pkAuthenticator.paChecksum.contents); + if (val->supportedCMSTypes) { + for (i = 0; val->supportedCMSTypes[i]; i++) + free_algorithm_identifier(NULL, val->supportedCMSTypes[i]); + free(val->supportedCMSTypes); + } + free(val->clientDHNonce.data); + val->clientPublicValue = NULL; + val->pkAuthenticator.paChecksum.contents = NULL; + val->supportedCMSTypes = NULL; + val->clientDHNonce.data = NULL; + return retval; +} + +asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val) +{ + setup(); + val->pkAuthenticator.kdcName = NULL; + val->clientPublicValue = NULL; + { begin_structure(); + get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9); + if (tagnum == 1) { + alloc_field(val->clientPublicValue); + val->clientPublicValue->algorithm.algorithm.data = NULL; + val->clientPublicValue->algorithm.parameters.data = NULL; + val->clientPublicValue->subjectPublicKey.data = NULL; + /* 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)) + clean_return(ASN1_BAD_ID); + if (tagnum == 1) { + retval = asn1_decode_subject_pk_info(&subbuf, + val->clientPublicValue); + if (retval) clean_return(retval); + if (!taglen && indef) { get_eoc(); } + next_tag(); + } else val->clientPublicValue = NULL; + } + } + end_structure(); + } + return 0; +error_out: + free(val->pkAuthenticator.kdcName); + if (val->clientPublicValue) { + free(val->clientPublicValue->algorithm.algorithm.data); + free(val->clientPublicValue->algorithm.parameters.data); + free(val->clientPublicValue->subjectPublicKey.data); + free(val->clientPublicValue); + } + val->pkAuthenticator.kdcName = NULL; + val->clientPublicValue = NULL; + return retval; +} + +asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val) +{ + setup(); + val->choice = choice_pa_pk_as_rep_UNKNOWN; + { begin_choice(); + if (tagnum == choice_pa_pk_as_rep_dhInfo) { + val->choice = choice_pa_pk_as_rep_dhInfo; + val->u.dh_Info.dhSignedData.data = NULL; + val->u.dh_Info.serverDHNonce.data = NULL; + 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; + val->u.encKeyPack.data = NULL; + 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(); + } + return 0; +error_out: + if (val->choice == choice_pa_pk_as_rep_dhInfo) { + free(val->u.dh_Info.dhSignedData.data); + free(val->u.dh_Info.serverDHNonce.data); + } else if (val->choice == choice_pa_pk_as_rep_encKeyPack) { + free(val->u.encKeyPack.data); + } + val->choice = choice_pa_pk_as_rep_UNKNOWN; + return retval; +} + +asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val) +{ + setup(); + val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN; + { begin_structure(); + if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) { + val->choice = choice_pa_pk_as_rep_draft9_dhSignedData; + val->u.dhSignedData.data = NULL; + 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; + val->u.encKeyPack.data = NULL; + 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(); + } + return 0; +error_out: + if (val->choice == choice_pa_pk_as_rep_draft9_dhSignedData) + free(val->u.dhSignedData.data); + else if (val->choice == choice_pa_pk_as_rep_draft9_encKeyPack) + free(val->u.encKeyPack.data); + val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN; + return retval; +} + +#endif /* DISABLE_PKINIT */ + +static void free_typed_data(void *dummy, krb5_typed_data *val) +{ + free(val->data); + free(val); +} + +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_ptr, + free_typed_data); +} + +asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val) +{ + setup(); + val->data = NULL; + { begin_structure(); + get_field(val->type,0,asn1_decode_int32); + get_lenfield(val->length,val->data,1,asn1_decode_octetstring); + end_structure(); + } + return 0; +error_out: + free(val->data); + val->data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_typed_data_ptr(asn1buf *buf, krb5_typed_data **valptr) +{ + decode_ptr(krb5_typed_data *, asn1_decode_typed_data); +} diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.h new file mode 100644 index 000000000..7444443ba --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_decode.h @@ -0,0 +1,281 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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 ( ), + *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 ( ), + *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 ( ) + 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_checksum_ptr + (asn1buf *buf, krb5_checksum **valptr); +asn1_error_code asn1_decode_encryption_key + (asn1buf *buf, krb5_keyblock *val); +asn1_error_code asn1_decode_encryption_key_ptr + (asn1buf *buf, krb5_keyblock **valptr); +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_ticket_ptr + (asn1buf *buf, krb5_ticket **valptr); +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_host_address_ptr + (asn1buf *buf, krb5_address **valptr); +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_last_req_entry_ptr + (asn1buf *buf, krb5_last_req_entry **valptr); +asn1_error_code asn1_decode_authdata_elt + (asn1buf *buf, krb5_authdata *val); +asn1_error_code asn1_decode_authdata_elt_ptr + (asn1buf *buf, krb5_authdata **valptr); +asn1_error_code asn1_decode_krb_cred_info + (asn1buf *buf, krb5_cred_info *val); +asn1_error_code asn1_decode_krb_cred_info_ptr + (asn1buf *buf, krb5_cred_info **valptr); +asn1_error_code asn1_decode_pa_data + (asn1buf *buf, krb5_pa_data *val); +asn1_error_code asn1_decode_pa_data_ptr + (asn1buf *buf, krb5_pa_data **valptr); +asn1_error_code asn1_decode_passwdsequence + (asn1buf *buf, passwd_phrase_element *val); +asn1_error_code asn1_decode_passwdsequence_ptr + (asn1buf *buf, passwd_phrase_element **valptr); +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_external_principal_identifier_ptr + (asn1buf *buf, krb5_external_principal_identifier **valptr); +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_trusted_ca_ptr + (asn1buf *buf, krb5_trusted_ca **valptr); +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_algorithm_identifier_ptr + (asn1buf *buf, krb5_algorithm_identifier **valptr); +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); +asn1_error_code asn1_decode_typed_data_ptr + (asn1buf *buf, krb5_typed_data **valptr); + +/* 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); + +asn1_error_code asn1_decode_setpw_req + (asn1buf *buf, krb5_data *rep, krb5_principal *principal); +asn1_error_code asn1_decode_pa_for_user + (asn1buf *buf, krb5_pa_for_user *val); +asn1_error_code asn1_decode_pa_pac_req + (asn1buf *buf, krb5_pa_pac_req *val); + +asn1_error_code asn1_decode_fast_armor +(asn1buf *buf, krb5_fast_armor *val); + +asn1_error_code asn1_decode_fast_armor_ptr +(asn1buf *buf, krb5_fast_armor **val); + +asn1_error_code asn1_decode_fast_finished +(asn1buf *buf, krb5_fast_finished *val); + +asn1_error_code asn1_decode_fast_finished_ptr +(asn1buf *buf, krb5_fast_finished **val); + +#endif diff --git a/krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.c new file mode 100644 index 000000000..3ddcfbd9e --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.c @@ -0,0 +1,1852 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/asn1_k_encode.c + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +/* helper macros + + These are mostly only needed for PKINIT, but there are three + basic-krb5 encoders not converted yet. */ + +/* 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 sum=0 + +/* form a sequence (by adding a sequence header to the current encoding) */ +#define asn1_makeseq()\ +{ unsigned int length;\ + retval = asn1_make_sequence(buf,sum,&length);\ + if (retval) {\ + return retval; }\ + sum += length; } + +/* produce the final output and clean up the workspace */ +#define asn1_cleanup()\ + *retlen = sum;\ + return 0 + +/* asn1_addfield -- add a field, or component, to the encoding */ +#define asn1_addfield(value,tag,encoder)\ +{ unsigned int length; \ + retval = encoder(buf,value,&length); \ + if (retval) {\ + return retval; }\ + sum += length;\ + retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ + if (retval) {\ + return retval; }\ + sum += length; } + +DEFINTTYPE(int32, krb5_int32); +DEFPTRTYPE(int32_ptr, int32); + +DEFUINTTYPE(uint, unsigned int); +DEFUINTTYPE(octet, krb5_octet); +DEFUINTTYPE(ui_4, krb5_ui_4); + +DEFFNLENTYPE(octetstring, unsigned char *, asn1_encode_octetstring); +DEFFNLENTYPE(s_octetstring, char *, asn1_encode_octetstring); +DEFFNLENTYPE(charstring, char *, asn1_encode_charstring); +DEFFNLENTYPE(generalstring, char *, asn1_encode_generalstring); +DEFFNLENTYPE(u_generalstring, unsigned char *, asn1_encode_generalstring); +DEFFNLENTYPE(opaque, char *, asn1_encode_opaque); + +DEFFIELDTYPE(gstring_data, krb5_data, + FIELDOF_STRING(krb5_data, generalstring, data, length, -1)); +DEFPTRTYPE(gstring_data_ptr,gstring_data); + +DEFFIELDTYPE(ostring_data, krb5_data, + FIELDOF_STRING(krb5_data, s_octetstring, data, length, -1)); +DEFPTRTYPE(ostring_data_ptr,ostring_data); + +DEFFIELDTYPE(opaque_data, krb5_data, + FIELDOF_STRING(krb5_data, opaque, data, length, -1)); + +DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, + FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1)); +DEFPTRTYPE(realm_of_principal, realm_of_principal_data); + + +static const struct field_info princname_fields[] = { + FIELDOF_NORM(krb5_principal_data, int32, type, 0), + FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, 1), +}; +/* krb5_principal is a typedef for krb5_principal_data*, so this is + effectively "encode_principal_data_at" with an address arg. */ +DEFSEQTYPE(principal_data, krb5_principal_data, princname_fields, 0); +DEFPTRTYPE(principal, principal_data); + +static asn1_error_code +asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val, + unsigned int *retlen) +{ + /* Range checking for time_t vs krb5_timestamp? */ + time_t tval = *val; + return asn1_encode_generaltime(buf, tval, retlen); +} +DEFFNXTYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at); + +const static struct field_info address_fields[] = { + FIELDOF_NORM(krb5_address, int32, addrtype, 0), + FIELDOF_STRING(krb5_address, octetstring, contents, length, 1), +}; +DEFSEQTYPE(address, krb5_address, address_fields, 0); +DEFPTRTYPE(address_ptr, address); + +DEFNULLTERMSEQOFTYPE(seq_of_host_addresses, address_ptr); +DEFPTRTYPE(ptr_seqof_host_addresses, seq_of_host_addresses); + +static unsigned int +optional_encrypted_data (const void *vptr) +{ + const krb5_enc_data *val = vptr; + unsigned int optional = 0; + + if (val->kvno != 0) + optional |= (1u << 1); + + return optional; +} + +static const struct field_info encrypted_data_fields[] = { + FIELDOF_NORM(krb5_enc_data, int32, enctype, 0), + FIELDOF_OPT(krb5_enc_data, uint, kvno, 1, 1), + FIELDOF_NORM(krb5_enc_data, ostring_data, ciphertext, 2), +}; +DEFSEQTYPE(encrypted_data, krb5_enc_data, encrypted_data_fields, + optional_encrypted_data); + +/* The encode_bitstring function wants an array of bytes (since PKINIT + may provide something that isn't 32 bits), but krb5_flags is stored + as a 32-bit integer in host order. */ +static asn1_error_code +asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val, + unsigned int *retlen) +{ + unsigned char cbuf[4]; + store_32_be((krb5_ui_4) *val, cbuf); + return asn1_encode_bitstring(buf, 4, cbuf, retlen); +} +DEFFNXTYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at); + +const static struct field_info authdata_elt_fields[] = { + /* ad-type[0] INTEGER */ + FIELDOF_NORM(krb5_authdata, int32, ad_type, 0), + /* ad-data[1] OCTET STRING */ + FIELDOF_STRING(krb5_authdata, octetstring, contents, length, 1), +}; +DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields, 0); +DEFPTRTYPE(authdata_elt_ptr, authdata_elt); +DEFNONEMPTYNULLTERMSEQOFTYPE(auth_data, authdata_elt_ptr); +DEFPTRTYPE(auth_data_ptr, auth_data); + +static const struct field_info encryption_key_fields[] = { + FIELDOF_NORM(krb5_keyblock, int32, enctype, 0), + FIELDOF_STRING(krb5_keyblock, octetstring, contents, length, 1), +}; +DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields, 0); +DEFPTRTYPE(ptr_encryption_key, encryption_key); + +static const struct field_info checksum_fields[] = { + FIELDOF_NORM(krb5_checksum, int32, checksum_type, 0), + FIELDOF_STRING(krb5_checksum, octetstring, contents, length, 1), +}; +DEFSEQTYPE(checksum, krb5_checksum, checksum_fields, 0); +DEFPTRTYPE(checksum_ptr, checksum); +DEFNULLTERMSEQOFTYPE(seq_of_checksum, checksum_ptr); +DEFPTRTYPE(ptr_seqof_checksum, seq_of_checksum); + +static const struct field_info lr_fields[] = { + FIELDOF_NORM(krb5_last_req_entry, int32, lr_type, 0), + FIELDOF_NORM(krb5_last_req_entry, kerberos_time, value, 1), +}; +DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields, 0); + +DEFPTRTYPE(last_req_ent_ptr, last_req_ent); +DEFNONEMPTYNULLTERMSEQOFTYPE(last_req, last_req_ent_ptr); +DEFPTRTYPE(last_req_ptr, last_req); + +static const struct field_info ticket_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELDOF_NORM(krb5_ticket, realm_of_principal, server, 1), + FIELDOF_NORM(krb5_ticket, principal, server, 2), + FIELDOF_NORM(krb5_ticket, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields, 0); +DEFAPPTAGGEDTYPE(ticket, 1, untagged_ticket); + +static const struct field_info pa_data_fields[] = { + FIELDOF_NORM(krb5_pa_data, int32, pa_type, 1), + FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 2), +}; +DEFSEQTYPE(pa_data, krb5_pa_data, pa_data_fields, 0); +DEFPTRTYPE(pa_data_ptr, pa_data); + +DEFNULLTERMSEQOFTYPE(seq_of_pa_data, pa_data_ptr); +DEFPTRTYPE(ptr_seqof_pa_data, seq_of_pa_data); + +DEFPTRTYPE(ticket_ptr, ticket); +DEFNONEMPTYNULLTERMSEQOFTYPE(seq_of_ticket,ticket_ptr); +DEFPTRTYPE(ptr_seqof_ticket, seq_of_ticket); + +/* EncKDCRepPart ::= SEQUENCE */ +static const struct field_info enc_kdc_rep_part_fields[] = { + /* key[0] EncryptionKey */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, ptr_encryption_key, session, 0), + /* last-req[1] LastReq */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, last_req_ptr, last_req, 1), + /* nonce[2] INTEGER */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, int32, nonce, 2), + /* key-expiration[3] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, key_exp, 3, 3), + /* flags[4] TicketFlags */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, krb5_flags, flags, 4), + /* authtime[5] KerberosTime */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.authtime, 5), + /* starttime[6] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.starttime, 6, 6), + /* endtime[7] KerberosTime */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.endtime, 7), + /* renew-till[8] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.renew_till, 8, 8), + /* srealm[9] Realm */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, realm_of_principal, server, 9), + /* sname[10] PrincipalName */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, principal, server, 10), + /* caddr[11] HostAddresses OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_host_addresses, caddrs, + 11, 11), + /* encrypted-pa-data[12] SEQUENCE OF PA-DATA OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_pa_data, enc_padata, 12, 12), +}; +static unsigned int optional_enc_kdc_rep_part(const void *p) +{ + const krb5_enc_kdc_rep_part *val = p; + unsigned int optional = 0; + + if (val->key_exp) + optional |= (1u << 3); + if (val->times.starttime) + optional |= (1u << 6); + if (val->flags & TKT_FLG_RENEWABLE) + optional |= (1u << 8); + if (val->caddrs != NULL && val->caddrs[0] != NULL) + optional |= (1u << 11); + + return optional; +} +DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields, + optional_enc_kdc_rep_part); + +/* Yuck! Eventually push this *up* above the encoder API and make the + rest of the library put the realm name in one consistent place. At + the same time, might as well add the msg-type field and encode both + AS-REQ and TGS-REQ through the same descriptor. */ +struct kdc_req_hack { + krb5_kdc_req v; + krb5_data *server_realm; +}; +static const struct field_info kdc_req_hack_fields[] = { + FIELDOF_NORM(struct kdc_req_hack, krb5_flags, v.kdc_options, 0), + FIELDOF_OPT(struct kdc_req_hack, principal, v.client, 1, 1), + FIELDOF_NORM(struct kdc_req_hack, gstring_data_ptr, server_realm, 2), + FIELDOF_OPT(struct kdc_req_hack, principal, v.server, 3, 3), + FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.from, 4, 4), + FIELDOF_NORM(struct kdc_req_hack, kerberos_time, v.till, 5), + FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.rtime, 6, 6), + FIELDOF_NORM(struct kdc_req_hack, int32, v.nonce, 7), + FIELDOF_SEQOF_INT32(struct kdc_req_hack, int32_ptr, v.ktype, v.nktypes, 8), + FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_host_addresses, v.addresses, 9, 9), + FIELDOF_OPT(struct kdc_req_hack, encrypted_data, v.authorization_data, 10, 10), + FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_ticket, v.second_ticket, 11, 11), +}; +static unsigned int optional_kdc_req_hack(const void *p) +{ + const struct kdc_req_hack *val2 = p; + const krb5_kdc_req *val = &val2->v; + unsigned int optional = 0; + + if (val->second_ticket != NULL && val->second_ticket[0] != NULL) + optional |= (1u << 11); + if (val->authorization_data.ciphertext.data != NULL) + optional |= (1u << 10); + if (val->addresses != NULL && val->addresses[0] != NULL) + optional |= (1u << 9); + if (val->rtime) + optional |= (1u << 6); + if (val->from) + optional |= (1u << 4); + if (val->server != NULL) + optional |= (1u << 3); + if (val->client != NULL) + optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(kdc_req_body_hack, struct kdc_req_hack, kdc_req_hack_fields, + optional_kdc_req_hack); +static asn1_error_code +asn1_encode_kdc_req_hack(asn1buf *, const struct kdc_req_hack *, + unsigned int *); +MAKE_ENCFN(asn1_encode_kdc_req_hack, kdc_req_body_hack); +static asn1_error_code +asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val, + unsigned int *retlen) +{ + struct kdc_req_hack val2; + val2.v = *val; + if (val->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + if (val->second_ticket != NULL && val->second_ticket[0] != NULL) { + val2.server_realm = &val->second_ticket[0]->server->realm; + } else return ASN1_MISSING_FIELD; + } else if (val->server != NULL) { + val2.server_realm = &val->server->realm; + } else return ASN1_MISSING_FIELD; + return asn1_encode_kdc_req_hack(buf, &val2, retlen); +} +DEFFNXTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); +/* end ugly hack */ + +DEFPTRTYPE(ptr_kdc_req_body,kdc_req_body); + +static const struct field_info transited_fields[] = { + FIELDOF_NORM(krb5_transited, octet, tr_type, 0), + FIELDOF_NORM(krb5_transited, ostring_data, tr_contents, 1), +}; +DEFSEQTYPE(transited, krb5_transited, transited_fields, 0); + +static const struct field_info krb_safe_body_fields[] = { + FIELDOF_NORM(krb5_safe, ostring_data, user_data, 0), + FIELDOF_OPT(krb5_safe, kerberos_time, timestamp, 1, 1), + FIELDOF_OPT(krb5_safe, int32, usec, 2, 2), + FIELDOF_OPT(krb5_safe, uint, seq_number, 3, 3), + FIELDOF_NORM(krb5_safe, address_ptr, s_address, 4), + FIELDOF_OPT(krb5_safe, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_krb_safe_body(const void *p) +{ + const krb5_safe *val = p; + unsigned int optional = 0; + + if (val->timestamp) { + optional |= (1u << 1); + optional |= (1u << 2); + } + if (val->seq_number) + optional |= (1u << 3); + if (val->r_address != NULL) + optional |= (1u << 5); + + return optional; +} +DEFSEQTYPE(krb_safe_body, krb5_safe, krb_safe_body_fields, + optional_krb_safe_body); + +static const struct field_info krb_cred_info_fields[] = { + FIELDOF_NORM(krb5_cred_info, ptr_encryption_key, session, 0), + FIELDOF_OPT(krb5_cred_info, realm_of_principal, client, 1, 1), + FIELDOF_OPT(krb5_cred_info, principal, client, 2, 2), + FIELDOF_OPT(krb5_cred_info, krb5_flags, flags, 3, 3), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.authtime, 4, 4), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.starttime, 5, 5), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.endtime, 6, 6), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.renew_till, 7, 7), + FIELDOF_OPT(krb5_cred_info, realm_of_principal, server, 8, 8), + FIELDOF_OPT(krb5_cred_info, principal, server, 9, 9), + FIELDOF_OPT(krb5_cred_info, ptr_seqof_host_addresses, caddrs, 10, 10), +}; +static unsigned int optional_krb_cred_info(const void *p) +{ + const krb5_cred_info *val = p; + unsigned int optional = 0; + + if (val->caddrs != NULL && val->caddrs[0] != NULL) + optional |= (1u << 10); + if (val->server != NULL) { + optional |= (1u << 9); + optional |= (1u << 8); + } + if (val->times.renew_till) + optional |= (1u << 7); + if (val->times.endtime) + optional |= (1u << 6); + if (val->times.starttime) + optional |= (1u << 5); + if (val->times.authtime) + optional |= (1u << 4); + if (val->flags) + optional |= (1u << 3); + if (val->client != NULL) { + optional |= (1u << 2); + optional |= (1u << 1); + } + + return optional; +} +DEFSEQTYPE(cred_info, krb5_cred_info, krb_cred_info_fields, + optional_krb_cred_info); +DEFPTRTYPE(cred_info_ptr, cred_info); +DEFNULLTERMSEQOFTYPE(seq_of_cred_info, cred_info_ptr); + +DEFPTRTYPE(ptrseqof_cred_info, seq_of_cred_info); + + + +static unsigned int +optional_etype_info_entry(const void *vptr) +{ + const krb5_etype_info_entry *val = vptr; + unsigned int optional = 0; + + if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT) + optional |= (1u << 1); + + return optional; +} +static const struct field_info etype_info_entry_fields[] = { + FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0), + FIELDOF_OPTSTRING(krb5_etype_info_entry, octetstring, salt, length, 1, 1), +}; +DEFSEQTYPE(etype_info_entry, krb5_etype_info_entry, etype_info_entry_fields, + optional_etype_info_entry); + +static unsigned int +optional_etype_info2_entry(const void *vptr) +{ + const krb5_etype_info_entry *val = vptr; + unsigned int optional = 0; + + if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT) + optional |= (1u << 1); + if (val->s2kparams.data) + optional |= (1u << 2); + + return optional; +} + +static const struct field_info etype_info2_entry_fields[] = { + FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0), + FIELDOF_OPTSTRING(krb5_etype_info_entry, u_generalstring, salt, length, + 1, 1), + FIELDOF_OPT(krb5_etype_info_entry, ostring_data, s2kparams, 2, 2), +}; +DEFSEQTYPE(etype_info2_entry, krb5_etype_info_entry, etype_info2_entry_fields, + optional_etype_info2_entry); + +DEFPTRTYPE(etype_info_entry_ptr, etype_info_entry); +DEFNULLTERMSEQOFTYPE(etype_info, etype_info_entry_ptr); + +DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry); +DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr); + +static const struct field_info passwdsequence_fields[] = { + FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, passwd, 0), + FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, phrase, 1), +}; +DEFSEQTYPE(passwdsequence, passwd_phrase_element, passwdsequence_fields, 0); + +DEFPTRTYPE(passwdsequence_ptr, passwdsequence); +DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_passwdsequence, passwdsequence_ptr); +DEFPTRTYPE(ptr_seqof_passwdsequence, seqof_passwdsequence); + + +static const struct field_info sam_challenge_fields[] = { + FIELDOF_NORM(krb5_sam_challenge, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_challenge, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_type_name, 2, 2), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_track_id,3, 3), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge_label,4, 4), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge,5, 5), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_response_prompt,6, 6), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_pk_for_sad,7, 7), + FIELDOF_OPT(krb5_sam_challenge, int32, sam_nonce, 8, 8), + FIELDOF_OPT(krb5_sam_challenge, checksum, sam_cksum, 9, 9), +}; +static unsigned int optional_sam_challenge(const void *p) +{ + const krb5_sam_challenge *val = p; + unsigned int optional = 0; + + if (val->sam_cksum.length) + optional |= (1u << 9); + + if (val->sam_nonce) + optional |= (1u << 8); + + if (val->sam_pk_for_sad.length > 0) optional |= (1u << 7); + if (val->sam_response_prompt.length > 0) optional |= (1u << 6); + if (val->sam_challenge.length > 0) optional |= (1u << 5); + if (val->sam_challenge_label.length > 0) optional |= (1u << 4); + if (val->sam_track_id.length > 0) optional |= (1u << 3); + if (val->sam_type_name.length > 0) optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(sam_challenge,krb5_sam_challenge,sam_challenge_fields, + optional_sam_challenge); + +#if 0 /* encoders not used! */ +MAKE_ENCFN(asn1_encode_sequence_of_checksum, seq_of_checksum); +static 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(val->sam_cksum, 1, asn1_encode_sequence_of_checksum); + + { + unsigned int length; + + retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length, + (unsigned char *)val->sam_challenge_2_body.data); + if (retval) { + 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) { + return retval; + } + sum += length; + } + + asn1_makeseq(); + asn1_cleanup(); +} +DEFFNXTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2); + +static const struct field_info sam_challenge_2_body_fields[] = { + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_challenge_2_body, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_type_name, 2, 2), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_track_id,3, 3), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge_label,4, 4), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge,5, 5), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_response_prompt,6, 6), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_pk_for_sad,7, 7), + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_nonce, 8), + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_etype, 9), +}; +static unsigned int optional_sam_challenge_2_body(const void *p) +{ + const krb5_sam_challenge_2_body *val = p; + unsigned int optional = 0; + + if (val->sam_pk_for_sad.length > 0) optional |= (1u << 7); + if (val->sam_response_prompt.length > 0) optional |= (1u << 6); + if (val->sam_challenge.length > 0) optional |= (1u << 5); + if (val->sam_challenge_label.length > 0) optional |= (1u << 4); + if (val->sam_track_id.length > 0) optional |= (1u << 3); + if (val->sam_type_name.length > 0) optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body,sam_challenge_2_body_fields, + optional_sam_challenge_2_body); +#endif + +static const struct field_info sam_key_fields[] = { + FIELDOF_NORM(krb5_sam_key, encryption_key, sam_key, 0), +}; +DEFSEQTYPE(sam_key, krb5_sam_key, sam_key_fields, 0); + +static const struct field_info enc_sam_response_enc_fields[] = { + FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_nonce, 0), + FIELDOF_NORM(krb5_enc_sam_response_enc, kerberos_time, sam_timestamp, 1), + FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_usec, 2), + FIELDOF_OPT(krb5_enc_sam_response_enc, ostring_data, sam_sad, 3, 3), +}; +static unsigned int optional_enc_sam_response_enc(const void *p) +{ + const krb5_enc_sam_response_enc *val = p; + unsigned int optional = 0; + + if (val->sam_sad.length > 0) optional |= (1u << 3); + + return optional; +} +DEFSEQTYPE(enc_sam_response_enc, krb5_enc_sam_response_enc, + enc_sam_response_enc_fields, optional_enc_sam_response_enc); + +static const struct field_info enc_sam_response_enc_2_fields[] = { + FIELDOF_NORM(krb5_enc_sam_response_enc_2, int32, sam_nonce, 0), + FIELDOF_OPT(krb5_enc_sam_response_enc_2, ostring_data, sam_sad, 1, 1), +}; +static unsigned int optional_enc_sam_response_enc_2(const void *p) +{ + const krb5_enc_sam_response_enc_2 *val = p; + unsigned int optional = 0; + + if (val->sam_sad.length > 0) optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(enc_sam_response_enc_2, krb5_enc_sam_response_enc_2, + enc_sam_response_enc_2_fields, optional_enc_sam_response_enc_2); + +static const struct field_info sam_response_fields[] = { + FIELDOF_NORM(krb5_sam_response, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_response, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_response, ostring_data, sam_track_id, 2, 2), + FIELDOF_OPT(krb5_sam_response, encrypted_data, sam_enc_key, 3, 3), + FIELDOF_NORM(krb5_sam_response, encrypted_data, sam_enc_nonce_or_ts, 4), + FIELDOF_OPT(krb5_sam_response, int32, sam_nonce, 5, 5), + FIELDOF_OPT(krb5_sam_response, kerberos_time, sam_patimestamp, 6, 6), +}; +static unsigned int optional_sam_response(const void *p) +{ + const krb5_sam_response *val = p; + unsigned int optional = 0; + + if (val->sam_patimestamp) + optional |= (1u << 6); + if (val->sam_nonce) + optional |= (1u << 5); + if (val->sam_enc_key.ciphertext.length) + optional |= (1u << 3); + if (val->sam_track_id.length > 0) optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(sam_response, krb5_sam_response, sam_response_fields, + optional_sam_response); + +static const struct field_info sam_response_2_fields[] = { + FIELDOF_NORM(krb5_sam_response_2, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_response_2, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_response_2, ostring_data, sam_track_id, 2, 2), + FIELDOF_NORM(krb5_sam_response_2, encrypted_data, sam_enc_nonce_or_sad, 3), + FIELDOF_NORM(krb5_sam_response_2, int32, sam_nonce, 4), +}; +static unsigned int optional_sam_response_2(const void *p) +{ + const krb5_sam_response_2 *val = p; + unsigned int optional = 0; + + if (val->sam_track_id.length > 0) optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(sam_response_2, krb5_sam_response_2, sam_response_2_fields, + optional_sam_response_2); + +static const struct field_info predicted_sam_response_fields[] = { + FIELDOF_NORM(krb5_predicted_sam_response, encryption_key, sam_key, 0), + FIELDOF_NORM(krb5_predicted_sam_response, krb5_flags, sam_flags, 1), + FIELDOF_NORM(krb5_predicted_sam_response, kerberos_time, stime, 2), + FIELDOF_NORM(krb5_predicted_sam_response, int32, susec, 3), + FIELDOF_NORM(krb5_predicted_sam_response, realm_of_principal, client, 4), + FIELDOF_NORM(krb5_predicted_sam_response, principal, client, 5), + FIELDOF_OPT(krb5_predicted_sam_response, ostring_data, msd, 6, 6), +}; +static unsigned int optional_predicted_sam_response(const void *p) +{ + const krb5_predicted_sam_response *val = p; + unsigned int optional = 0; + + if (val->msd.length > 0) optional |= (1u << 6); + + return optional; +} +DEFSEQTYPE(predicted_sam_response, krb5_predicted_sam_response, + predicted_sam_response_fields, + optional_predicted_sam_response); + +static const struct field_info krb5_authenticator_fields[] = { + /* Authenticator ::= [APPLICATION 2] SEQUENCE */ + /* authenticator-vno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* crealm[1] Realm */ + FIELDOF_NORM(krb5_authenticator, realm_of_principal, client, 1), + /* cname[2] PrincipalName */ + FIELDOF_NORM(krb5_authenticator, principal, client, 2), + /* cksum[3] Checksum OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, checksum_ptr, checksum, 3, 3), + /* cusec[4] INTEGER */ + FIELDOF_NORM(krb5_authenticator, int32, cusec, 4), + /* ctime[5] KerberosTime */ + FIELDOF_NORM(krb5_authenticator, kerberos_time, ctime, 5), + /* subkey[6] EncryptionKey OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, ptr_encryption_key, subkey, 6, 6), + /* seq-number[7] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, uint, seq_number, 7, 7), + /* authorization-data[8] AuthorizationData OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, auth_data_ptr, authorization_data, 8, 8), +}; +static unsigned int optional_krb5_authenticator(const void *p) +{ + const krb5_authenticator *val = p; + unsigned int optional = 0; + + if (val->authorization_data != NULL && val->authorization_data[0] != NULL) + optional |= (1u << 8); + + if (val->seq_number != 0) + optional |= (1u << 7); + + if (val->subkey != NULL) + optional |= (1u << 6); + + if (val->checksum != NULL) + optional |= (1u << 3); + + return optional; +} +DEFSEQTYPE(untagged_krb5_authenticator, krb5_authenticator, krb5_authenticator_fields, + optional_krb5_authenticator); +DEFAPPTAGGEDTYPE(krb5_authenticator, 2, untagged_krb5_authenticator); + +static const struct field_info enc_tkt_part_fields[] = { + /* EncTicketPart ::= [APPLICATION 3] SEQUENCE */ + /* flags[0] TicketFlags */ + FIELDOF_NORM(krb5_enc_tkt_part, krb5_flags, flags, 0), + /* key[1] EncryptionKey */ + FIELDOF_NORM(krb5_enc_tkt_part, ptr_encryption_key, session, 1), + /* crealm[2] Realm */ + FIELDOF_NORM(krb5_enc_tkt_part, realm_of_principal, client, 2), + /* cname[3] PrincipalName */ + FIELDOF_NORM(krb5_enc_tkt_part, principal, client, 3), + /* transited[4] TransitedEncoding */ + FIELDOF_NORM(krb5_enc_tkt_part, transited, transited, 4), + /* authtime[5] KerberosTime */ + FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.authtime, 5), + /* starttime[6] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.starttime, 6, 6), + /* endtime[7] KerberosTime */ + FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.endtime, 7), + /* renew-till[8] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.renew_till, 8, 8), + /* caddr[9] HostAddresses OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, ptr_seqof_host_addresses, caddrs, 9, 9), + /* authorization-data[10] AuthorizationData OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, auth_data_ptr, authorization_data, 10, 10), +}; +static unsigned int optional_enc_tkt_part(const void *p) +{ + const krb5_enc_tkt_part *val = p; + unsigned int optional = 0; + + if (val->authorization_data != NULL && val->authorization_data[0] != NULL) + optional |= (1u << 10); + if (val->caddrs != NULL && val->caddrs[0] != NULL) + optional |= (1u << 9); + if (val->times.renew_till) + optional |= (1u << 8); + if (val->times.starttime) + optional |= (1u << 6); + + return optional; +} +DEFSEQTYPE(untagged_enc_tkt_part, krb5_enc_tkt_part, enc_tkt_part_fields, + optional_enc_tkt_part); +DEFAPPTAGGEDTYPE(enc_tkt_part, 3, untagged_enc_tkt_part); + +DEFAPPTAGGEDTYPE(enc_tgs_rep_part, 26, enc_kdc_rep_part); + +static const struct field_info as_rep_fields[] = { + /* AS-REP ::= [APPLICATION 11] KDC-REP */ + /* But KDC-REP needs to know what type it's being encapsulated + in, so expand each version. */ + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(KRB5_AS_REP, 1), + FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 2), + FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3), + FIELDOF_NORM(krb5_kdc_rep, principal, client, 4), + FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5), + FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6), +}; +static unsigned int optional_as_rep(const void *p) +{ + const krb5_kdc_rep *val = p; + unsigned int optional = 0; + + if (val->padata != NULL && val->padata[0] != NULL) + optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(untagged_as_rep, krb5_kdc_rep, as_rep_fields, optional_as_rep); +DEFAPPTAGGEDTYPE(as_rep, 11, untagged_as_rep); + +static const struct field_info tgs_rep_fields[] = { + /* TGS-REP ::= [APPLICATION 13] KDC-REP */ + /* But KDC-REP needs to know what type it's being encapsulated + in, so expand each version. */ + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(KRB5_TGS_REP, 1), + FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 2), + FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3), + FIELDOF_NORM(krb5_kdc_rep, principal, client, 4), + FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5), + FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6), +}; +static unsigned int optional_tgs_rep(const void *p) +{ + const krb5_kdc_rep *val = p; + unsigned int optional = 0; + + if (val->padata != NULL && val->padata[0] != NULL) + optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(untagged_tgs_rep, krb5_kdc_rep, tgs_rep_fields, optional_tgs_rep); +DEFAPPTAGGEDTYPE(tgs_rep, 13, untagged_tgs_rep); + +static const struct field_info ap_req_fields[] = { + /* AP-REQ ::= [APPLICATION 14] SEQUENCE */ + /* pvno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_AP_REQ, 1), + /* ap-options[2] APOptions */ + FIELDOF_NORM(krb5_ap_req, krb5_flags, ap_options, 2), + /* ticket[3] Ticket */ + FIELDOF_NORM(krb5_ap_req, ticket_ptr, ticket, 3), + /* authenticator[4] EncryptedData */ + FIELDOF_NORM(krb5_ap_req, encrypted_data, authenticator, 4), +}; +DEFSEQTYPE(untagged_ap_req, krb5_ap_req, ap_req_fields, 0); +DEFAPPTAGGEDTYPE(ap_req, 14, untagged_ap_req); + +static const struct field_info ap_rep_fields[] = { + /* AP-REP ::= [APPLICATION 15] SEQUENCE */ + /* pvno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_AP_REP, 1), + /* enc-part[2] EncryptedData */ + FIELDOF_NORM(krb5_ap_rep, encrypted_data, enc_part, 2), +}; +DEFSEQTYPE(untagged_ap_rep, krb5_ap_rep, ap_rep_fields, 0); +DEFAPPTAGGEDTYPE(ap_rep, 15, untagged_ap_rep); + +static const struct field_info ap_rep_enc_part_fields[] = { + /* EncAPRepPart ::= [APPLICATION 27] SEQUENCE */ + /* ctime[0] KerberosTime */ + FIELDOF_NORM(krb5_ap_rep_enc_part, kerberos_time, ctime, 0), + /* cusec[1] INTEGER */ + FIELDOF_NORM(krb5_ap_rep_enc_part, int32, cusec, 1), + /* subkey[2] EncryptionKey OPTIONAL */ + FIELDOF_OPT(krb5_ap_rep_enc_part, ptr_encryption_key, subkey, 2, 2), + /* seq-number[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_ap_rep_enc_part, uint, seq_number, 3, 3), +}; +static unsigned int optional_ap_rep_enc_part(const void *p) +{ + const krb5_ap_rep_enc_part *val = p; + unsigned int optional = 0; + + if (val->seq_number) + optional |= (1u << 3); + if (val->subkey != NULL) + optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(untagged_ap_rep_enc_part, krb5_ap_rep_enc_part, + ap_rep_enc_part_fields, optional_ap_rep_enc_part); +DEFAPPTAGGEDTYPE(ap_rep_enc_part, 27, untagged_ap_rep_enc_part); + +static const struct field_info as_req_fields[] = { + /* AS-REQ ::= [APPLICATION 10] KDC-REQ */ + FIELD_INT_IMM(KVNO, 1), + FIELD_INT_IMM(KRB5_AS_REQ, 2), + FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 3), + FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4), +}; +static unsigned int optional_as_req(const void *p) +{ + const krb5_kdc_req *val = p; + unsigned int optional = 0; + + if (val->padata != NULL && val->padata[0] != NULL) + optional |= (1u << 3); + + return optional; +} +DEFSEQTYPE(untagged_as_req, krb5_kdc_req, as_req_fields, optional_as_req); +DEFAPPTAGGEDTYPE(as_req, 10, untagged_as_req); + +static const struct field_info tgs_req_fields[] = { + /* TGS-REQ ::= [APPLICATION 12] KDC-REQ */ + FIELD_INT_IMM(KVNO, 1), + FIELD_INT_IMM(KRB5_TGS_REQ, 2), + FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 3), + FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4), +}; +static unsigned int optional_tgs_req(const void *p) +{ + const krb5_kdc_req *val = p; + unsigned int optional = 0; + + if (val->padata != NULL && val->padata[0] != NULL) + optional |= (1u << 3); + + return optional; +} +DEFSEQTYPE(untagged_tgs_req, krb5_kdc_req, tgs_req_fields, + optional_tgs_req); +DEFAPPTAGGEDTYPE(tgs_req, 12, untagged_tgs_req); + +static const struct field_info krb5_safe_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(ASN1_KRB_SAFE,1), + FIELD_SELF(krb_safe_body, 2), + FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, 3), +}; +DEFSEQTYPE(untagged_krb5_safe, krb5_safe, krb5_safe_fields, 0); +DEFAPPTAGGEDTYPE(krb5_safe, 20, untagged_krb5_safe); + +DEFPTRTYPE(krb_saved_safe_body_ptr, opaque_data); +DEFFIELDTYPE(krb5_safe_checksum_only, krb5_safe, + FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, -1)); +DEFPTRTYPE(krb5_safe_checksum_only_ptr, krb5_safe_checksum_only); +static const struct field_info krb5_safe_with_body_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(ASN1_KRB_SAFE,1), + FIELDOF_NORM(struct krb5_safe_with_body, krb_saved_safe_body_ptr, body, 2), + FIELDOF_NORM(struct krb5_safe_with_body, krb5_safe_checksum_only_ptr, safe, 3), +}; +DEFSEQTYPE(untagged_krb5_safe_with_body, struct krb5_safe_with_body, + krb5_safe_with_body_fields, 0); +DEFAPPTAGGEDTYPE(krb5_safe_with_body, 20, untagged_krb5_safe_with_body); + +static const struct field_info priv_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(ASN1_KRB_PRIV, 1), + FIELDOF_NORM(krb5_priv, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_priv, krb5_priv, priv_fields, 0); +DEFAPPTAGGEDTYPE(krb5_priv, 21, untagged_priv); + +static const struct field_info priv_enc_part_fields[] = { + FIELDOF_NORM(krb5_priv_enc_part, ostring_data, user_data, 0), + FIELDOF_OPT(krb5_priv_enc_part, kerberos_time, timestamp, 1, 1), + FIELDOF_OPT(krb5_priv_enc_part, int32, usec, 2, 2), + FIELDOF_OPT(krb5_priv_enc_part, uint, seq_number, 3, 3), + FIELDOF_NORM(krb5_priv_enc_part, address_ptr, s_address, 4), + FIELDOF_OPT(krb5_priv_enc_part, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_priv_enc_part(const void *p) +{ + const krb5_priv_enc_part *val = p; + unsigned int optional = 0; + + if (val->timestamp) { + optional |= (1u << 2); + optional |= (1u << 1); + } + if (val->seq_number) + optional |= (1u << 3); + if (val->r_address) + optional |= (1u << 5); + + return optional; +} +DEFSEQTYPE(untagged_priv_enc_part, krb5_priv_enc_part, priv_enc_part_fields, + optional_priv_enc_part); +DEFAPPTAGGEDTYPE(priv_enc_part, 28, untagged_priv_enc_part); + +static const struct field_info cred_fields[] = { + /* KRB-CRED ::= [APPLICATION 22] SEQUENCE */ + /* pvno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* msg-type[1] INTEGER, -- KRB_CRED */ + FIELD_INT_IMM(ASN1_KRB_CRED, 1), + /* tickets[2] SEQUENCE OF Ticket */ + FIELDOF_NORM(krb5_cred, ptr_seqof_ticket, tickets, 2), + /* enc-part[3] EncryptedData */ + FIELDOF_NORM(krb5_cred, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_cred, krb5_cred, cred_fields, 0); +DEFAPPTAGGEDTYPE(krb5_cred, 22, untagged_cred); + +static const struct field_info enc_cred_part_fields[] = { + /* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE */ + /* ticket-info[0] SEQUENCE OF KrbCredInfo */ + FIELDOF_NORM(krb5_cred_enc_part, ptrseqof_cred_info, ticket_info, 0), + /* nonce[1] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, int32, nonce, 1, 1), + /* timestamp[2] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, kerberos_time, timestamp, 2, 2), + /* usec[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, int32, usec, 3, 3), + /* s-address[4] HostAddress OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, address_ptr, s_address, 4, 4), + /* r-address[5] HostAddress OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_enc_cred_part(const void *p) +{ + const krb5_cred_enc_part *val = p; + unsigned int optional = 0; + + if (val->r_address != NULL) + optional |= (1u << 5); + + if (val->s_address != NULL) + optional |= (1u << 4); + + if (val->timestamp) { + optional |= (1u << 2); + optional |= (1u << 3); + } + + if (val->nonce) + optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(untagged_enc_cred_part, krb5_cred_enc_part, enc_cred_part_fields, + optional_enc_cred_part); +DEFAPPTAGGEDTYPE(enc_cred_part, 29, untagged_enc_cred_part); + +static const struct field_info error_fields[] = { + /* KRB-ERROR ::= [APPLICATION 30] SEQUENCE */ + /* pvno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_ERROR, 1), + /* ctime[2] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_error, kerberos_time, ctime, 2, 2), + /* cusec[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_error, int32, cusec, 3, 3), + /* stime[4] KerberosTime */ + FIELDOF_NORM(krb5_error, kerberos_time, stime, 4), + /* susec[5] INTEGER */ + FIELDOF_NORM(krb5_error, int32, susec, 5), + /* error-code[6] INTEGER */ + FIELDOF_NORM(krb5_error, ui_4, error, 6), + /* crealm[7] Realm OPTIONAL */ + FIELDOF_OPT(krb5_error, realm_of_principal, client, 7, 7), + /* cname[8] PrincipalName OPTIONAL */ + FIELDOF_OPT(krb5_error, principal, client, 8, 8), + /* realm[9] Realm -- Correct realm */ + FIELDOF_NORM(krb5_error, realm_of_principal, server, 9), + /* sname[10] PrincipalName -- Correct name */ + FIELDOF_NORM(krb5_error, principal, server, 10), + /* e-text[11] GeneralString OPTIONAL */ + FIELDOF_OPT(krb5_error, gstring_data, text, 11, 11), + /* e-data[12] OCTET STRING OPTIONAL */ + FIELDOF_OPT(krb5_error, ostring_data, e_data, 12, 12), +}; +static unsigned int optional_error(const void *p) +{ + const krb5_error *val = p; + unsigned int optional = 0; + + if (val->ctime) + optional |= (1u << 2); + if (val->cusec) + optional |= (1u << 3); + if (val->client) { + optional |= (1u << 7); + optional |= (1u << 8); + } + if (val->text.data != NULL && val->text.length > 0) + optional |= (1u << 11); + if (val->e_data.data != NULL && val->e_data.length > 0) + optional |= (1u << 12); + + return optional; +} +DEFSEQTYPE(untagged_krb5_error, krb5_error, error_fields, optional_error); +DEFAPPTAGGEDTYPE(krb5_error, 30, untagged_krb5_error); + +static const struct field_info alt_method_fields[] = { + FIELDOF_NORM(krb5_alt_method, int32, method, 0), + FIELDOF_OPTSTRING(krb5_alt_method, octetstring, data, length, 1, 1), +}; +static unsigned int +optional_alt_method(const void *p) +{ + const krb5_alt_method *a = p; + unsigned int optional = 0; + + if (a->data != NULL && a->length > 0) + optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(alt_method, krb5_alt_method, alt_method_fields, optional_alt_method); + +static const struct field_info pa_enc_ts_fields[] = { + FIELDOF_NORM(krb5_pa_enc_ts, kerberos_time, patimestamp, 0), + FIELDOF_OPT(krb5_pa_enc_ts, int32, pausec, 1, 1), +}; +static unsigned int +optional_pa_enc_ts(const void *p) +{ + const krb5_pa_enc_ts *val = p; + unsigned int optional = 0; + + if (val->pausec) + optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(pa_enc_ts, krb5_pa_enc_ts, pa_enc_ts_fields, optional_pa_enc_ts); + +static const struct field_info pwd_data_fields[] = { + FIELDOF_NORM(krb5_pwd_data, int32, sequence_count, 0), + FIELDOF_NORM(krb5_pwd_data, ptr_seqof_passwdsequence, element, 1), +}; +DEFSEQTYPE(pwd_data, krb5_pwd_data, pwd_data_fields, 0); + +static const struct field_info setpw_req_fields[] = { + FIELDOF_NORM(struct krb5_setpw_req, ostring_data, password, 0), + FIELDOF_NORM(struct krb5_setpw_req, principal, target, 1), + FIELDOF_NORM(struct krb5_setpw_req, realm_of_principal, target, 2), +}; + +DEFSEQTYPE(setpw_req, struct krb5_setpw_req, setpw_req_fields, 0); + +/* [MS-SFU] Section 2.2.1. */ +static const struct field_info pa_for_user_fields[] = { + FIELDOF_NORM(krb5_pa_for_user, principal, user, 0), + FIELDOF_NORM(krb5_pa_for_user, realm_of_principal, user, 1), + FIELDOF_NORM(krb5_pa_for_user, checksum, cksum, 2), + FIELDOF_NORM(krb5_pa_for_user, gstring_data, auth_package, 3), +}; + +DEFSEQTYPE(pa_for_user, krb5_pa_for_user, pa_for_user_fields, 0); + +/* draft-ietf-krb-wg-kerberos-referrals Appendix A. */ +static const struct field_info pa_svr_referral_data_fields[] = { + FIELDOF_NORM(krb5_pa_svr_referral_data, realm_of_principal, principal, 0), + FIELDOF_OPT(krb5_pa_svr_referral_data, principal, principal, 1, 1), +}; + +DEFSEQTYPE(pa_svr_referral_data, krb5_pa_svr_referral_data, pa_svr_referral_data_fields, 0); + +/* draft-ietf-krb-wg-kerberos-referrals Section 8. */ +static const struct field_info pa_server_referral_data_fields[] = { + FIELDOF_OPT(krb5_pa_server_referral_data, gstring_data_ptr, referred_realm, 0, 0), + FIELDOF_OPT(krb5_pa_server_referral_data, principal, true_principal_name, 1, 1), + FIELDOF_OPT(krb5_pa_server_referral_data, principal, requested_principal_name, 2, 2), + FIELDOF_OPT(krb5_pa_server_referral_data, kerberos_time, referral_valid_until, 3, 3), + FIELDOF_NORM(krb5_pa_server_referral_data, checksum, rep_cksum, 4), +}; + +DEFSEQTYPE(pa_server_referral_data, krb5_pa_server_referral_data, pa_server_referral_data_fields, 0); + +#if 0 +/* draft-brezak-win2k-krb-authz Section 6. */ +static const struct field_info pa_pac_request_fields[] = { + FIELDOF_NORM(krb5_pa_pac_req, boolean, include_pac, 0), +}; + +DEFSEQTYPE(pa_pac_request, krb5_pa_pac_req, pa_pac_request_fields, 0); +#endif + +/* RFC 4537 */ +DEFFIELDTYPE(etype_list, krb5_etype_list, + FIELDOF_SEQOF_INT32(krb5_etype_list, int32_ptr, etypes, length, -1)); + +/* draft-ietf-krb-wg-preauth-framework-09 */ +static const struct field_info fast_armor_fields[] = { + FIELDOF_NORM(krb5_fast_armor, int32, armor_type, 0), + FIELDOF_NORM( krb5_fast_armor, ostring_data, armor_value, 1), +}; + +DEFSEQTYPE( fast_armor, krb5_fast_armor, fast_armor_fields, 0); +DEFPTRTYPE( ptr_fast_armor, fast_armor); + +static const struct field_info fast_armored_req_fields[] = { + FIELDOF_OPT( krb5_fast_armored_req, ptr_fast_armor, armor, 0, 0), + FIELDOF_NORM( krb5_fast_armored_req, checksum, req_checksum, 1), + FIELDOF_NORM( krb5_fast_armored_req, encrypted_data, enc_part, 2), +}; + +static unsigned int fast_armored_req_optional (const void *p) { + const krb5_fast_armored_req *val = p; + unsigned int optional = 0; + if (val->armor) + optional |= (1u)<<0; + return optional; +} + +DEFSEQTYPE( fast_armored_req, krb5_fast_armored_req, fast_armored_req_fields, fast_armored_req_optional); +DEFFIELDTYPE( pa_fx_fast_request, krb5_fast_armored_req, + FIELDOF_ENCODEAS( krb5_fast_armored_req, fast_armored_req, 0)); + +DEFFIELDTYPE(fast_req_padata, krb5_kdc_req, + FIELDOF_NORM(krb5_kdc_req, ptr_seqof_pa_data, padata, -1)); +DEFPTRTYPE(ptr_fast_req_padata, fast_req_padata); + +static const struct field_info fast_req_fields[] = { + FIELDOF_NORM(krb5_fast_req, krb5_flags, fast_options, 0), + FIELDOF_NORM( krb5_fast_req, ptr_fast_req_padata, req_body, 1), + FIELDOF_NORM( krb5_fast_req, ptr_kdc_req_body, req_body, 2), +}; + +DEFSEQTYPE(fast_req, krb5_fast_req, fast_req_fields, 0); + + +static const struct field_info fast_finished_fields[] = { + FIELDOF_NORM( krb5_fast_finished, kerberos_time, timestamp, 0), + FIELDOF_NORM( krb5_fast_finished, int32, usec, 1), + FIELDOF_NORM( krb5_fast_finished, realm_of_principal, client, 2), + FIELDOF_NORM(krb5_fast_finished, principal, client, 3), + FIELDOF_NORM( krb5_fast_finished, checksum, ticket_checksum, 4), +}; + +DEFSEQTYPE( fast_finished, krb5_fast_finished, fast_finished_fields, 0); + +DEFPTRTYPE( ptr_fast_finished, fast_finished); + +static const struct field_info fast_response_fields[] = { + FIELDOF_NORM(krb5_fast_response, ptr_seqof_pa_data, padata, 0), + FIELDOF_OPT( krb5_fast_response, ptr_encryption_key, strengthen_key, 1, 1), + FIELDOF_OPT( krb5_fast_response, ptr_fast_finished, finished, 2, 2), + FIELDOF_NORM(krb5_fast_response, int32, nonce, 3), +}; + +static unsigned int fast_response_optional (const void *p) +{ + unsigned int optional = 0; + const krb5_fast_response *val = p; + if (val->strengthen_key) + optional |= (1u <<1); + if (val->finished) + optional |= (1u<<2); + return optional; +} +DEFSEQTYPE( fast_response, krb5_fast_response, fast_response_fields, fast_response_optional); + +static const struct field_info fast_rep_fields[] = { + FIELDOF_ENCODEAS(krb5_enc_data, encrypted_data, 0), +}; +DEFSEQTYPE(fast_rep, krb5_enc_data, fast_rep_fields, 0); + +DEFFIELDTYPE(pa_fx_fast_reply, krb5_enc_data, + FIELDOF_ENCODEAS(krb5_enc_data, fast_rep, 0)); + + + + +/* Exported complete encoders -- these produce a krb5_data with + the encoding in the correct byte order. */ + +MAKE_FULL_ENCODER(encode_krb5_authenticator, krb5_authenticator); +MAKE_FULL_ENCODER(encode_krb5_ticket, ticket); +MAKE_FULL_ENCODER(encode_krb5_encryption_key, encryption_key); +MAKE_FULL_ENCODER(encode_krb5_enc_tkt_part, enc_tkt_part); +/* XXX We currently (for backwards compatibility) encode both + EncASRepPart and EncTGSRepPart with application tag 26. */ +MAKE_FULL_ENCODER(encode_krb5_enc_kdc_rep_part, enc_tgs_rep_part); +MAKE_FULL_ENCODER(encode_krb5_as_rep, as_rep); +MAKE_FULL_ENCODER(encode_krb5_tgs_rep, tgs_rep); +MAKE_FULL_ENCODER(encode_krb5_ap_req, ap_req); +MAKE_FULL_ENCODER(encode_krb5_ap_rep, ap_rep); +MAKE_FULL_ENCODER(encode_krb5_ap_rep_enc_part, ap_rep_enc_part); +MAKE_FULL_ENCODER(encode_krb5_as_req, as_req); +MAKE_FULL_ENCODER(encode_krb5_tgs_req, tgs_req); +MAKE_FULL_ENCODER(encode_krb5_kdc_req_body, kdc_req_body); +MAKE_FULL_ENCODER(encode_krb5_safe, krb5_safe); + +/* + * encode_krb5_safe_with_body + * + * Like encode_krb5_safe(), except takes a saved KRB-SAFE-BODY + * encoding to avoid problems with re-encoding. + */ +MAKE_FULL_ENCODER(encode_krb5_safe_with_body, krb5_safe_with_body); + +MAKE_FULL_ENCODER(encode_krb5_priv, krb5_priv); +MAKE_FULL_ENCODER(encode_krb5_enc_priv_part, priv_enc_part); +MAKE_FULL_ENCODER(encode_krb5_cred, krb5_cred); +MAKE_FULL_ENCODER(encode_krb5_enc_cred_part, enc_cred_part); +MAKE_FULL_ENCODER(encode_krb5_error, krb5_error); +MAKE_FULL_ENCODER(encode_krb5_authdata, auth_data); +MAKE_FULL_ENCODER(encode_krb5_authdata_elt, authdata_elt); +MAKE_FULL_ENCODER(encode_krb5_alt_method, alt_method); +MAKE_FULL_ENCODER(encode_krb5_etype_info, etype_info); +MAKE_FULL_ENCODER(encode_krb5_etype_info2, etype_info2); +MAKE_FULL_ENCODER(encode_krb5_enc_data, encrypted_data); +MAKE_FULL_ENCODER(encode_krb5_pa_enc_ts, pa_enc_ts); +/* Sandia Additions */ +MAKE_FULL_ENCODER(encode_krb5_pwd_sequence, passwdsequence); +MAKE_FULL_ENCODER(encode_krb5_pwd_data, pwd_data); +MAKE_FULL_ENCODER(encode_krb5_padata_sequence, seq_of_pa_data); +/* sam preauth additions */ +MAKE_FULL_ENCODER(encode_krb5_sam_challenge, sam_challenge); +#if 0 /* encoders not used! */ +MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2, sam_challenge_2); +MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2_body, + sam_challenge_2_body); +#endif +MAKE_FULL_ENCODER(encode_krb5_sam_key, sam_key); +MAKE_FULL_ENCODER(encode_krb5_enc_sam_response_enc, + enc_sam_response_enc); +MAKE_FULL_ENCODER(encode_krb5_enc_sam_response_enc_2, + enc_sam_response_enc_2); +MAKE_FULL_ENCODER(encode_krb5_sam_response, sam_response); +MAKE_FULL_ENCODER(encode_krb5_sam_response_2, sam_response_2); +MAKE_FULL_ENCODER(encode_krb5_predicted_sam_response, + predicted_sam_response); +MAKE_FULL_ENCODER(encode_krb5_setpw_req, setpw_req); +MAKE_FULL_ENCODER(encode_krb5_pa_for_user, pa_for_user); +MAKE_FULL_ENCODER(encode_krb5_pa_svr_referral_data, pa_svr_referral_data); +MAKE_FULL_ENCODER(encode_krb5_pa_server_referral_data, pa_server_referral_data); +MAKE_FULL_ENCODER(encode_krb5_etype_list, etype_list); + +MAKE_FULL_ENCODER(encode_krb5_pa_fx_fast_request, pa_fx_fast_request); +MAKE_FULL_ENCODER( encode_krb5_fast_req, fast_req); +MAKE_FULL_ENCODER( encode_krb5_pa_fx_fast_reply, pa_fx_fast_reply); +MAKE_FULL_ENCODER(encode_krb5_fast_response, fast_response); + + + + + + +/* + * PKINIT + */ + +/* This code hasn't been converted to use the above framework yet, + because we currently have no test cases to validate the new + version. It *also* appears that some of the encodings may disagree + with the specifications, but that's a separate problem. */ + +/**** 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 + +/* asn1_addlenfield -- add a field whose length must be separately specified */ +#define asn1_addlenfield(len,value,tag,encoder)\ +{ unsigned int length; \ + retval = encoder(buf,len,value,&length); \ + if (retval) {\ + return retval; }\ + sum += length;\ + retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ + if (retval) {\ + return retval; }\ + sum += length; } + +/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */ +#define asn1_addfield_implicit(value,tag,encoder)\ +{ unsigned int length;\ + retval = encoder(buf,value,&length);\ + if (retval) {\ + return retval; }\ + sum += length;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } + +/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */ +#define asn1_insert_implicit_octetstring(len,value,tag)\ +{ unsigned int length;\ + retval = asn1buf_insert_octetstring(buf,len,value);\ + if (retval) {\ + return retval; }\ + sum += len;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } + +/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */ +/* needs "length" declared in enclosing context */ +#define asn1_insert_implicit_bitstring(len,value,tag)\ +{ retval = asn1buf_insert_octetstring(buf,len,value); \ + if (retval) {\ + return retval; }\ + sum += len;\ + retval = asn1buf_insert_octet(buf, 0);\ + if (retval) {\ + return retval; }\ + sum++;\ + retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } + +#ifndef DISABLE_PKINIT + +/* Callable encoders for the types defined above, until the PKINIT + encoders get converted. */ +MAKE_ENCFN(asn1_encode_realm, realm_of_principal_data); +MAKE_ENCFN(asn1_encode_principal_name, principal_data); +MAKE_ENCFN(asn1_encode_encryption_key, encryption_key); +MAKE_ENCFN(asn1_encode_checksum, checksum); + +static asn1_error_code +asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, + unsigned int *retlen) +{ + return asn1_encode_kerberos_time_at(buf,&val,retlen); +} + +/* Now the real PKINIT encoder functions. */ +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) + return retval; + sum += val->parameters.length; + } + + { + unsigned int length; + retval = asn1_encode_oid(buf, val->algorithm.length, + val->algorithm.data, + &length); + + if (retval) + 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(); + + { + unsigned int length; + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING); + } + + if (val->algorithm.parameters.length != 0) { + unsigned int length; + + retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length, + val->algorithm.parameters.data); + if (retval) + return retval; + sum += val->algorithm.parameters.length; + + retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, + val->algorithm.algorithm.data, + &length); + + if (retval) + return retval; + sum += length; + + + retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, + val->algorithm.parameters.length + length, + &length); + + if (retval) + 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--) { + unsigned int length; + 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--) { + unsigned int length; + 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--) { + unsigned int length; + 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); + + { + unsigned int length; + + 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) + 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(); + { + unsigned int length; + retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length); + if (retval) + return retval; + /* length set but ignored? sum not updated? */ + } + asn1_cleanup(); +} + +#endif /* DISABLE_PKINIT */ + +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--) { + unsigned int length; + + 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-7/src/lib/krb5/asn.1/asn1_k_encode.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.h new file mode 100644 index 000000000..94b8f7b60 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_k_encode.h @@ -0,0 +1,136 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/asn1_k_encode.h + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include "asn1buf.h" + +/* +**** 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. +*/ + +/* 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-7/src/lib/krb5/asn.1/asn1_make.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_make.c new file mode 100644 index 000000000..c4f740c7f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_make.c @@ -0,0 +1,161 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/krb5/asn.1/asn1_make.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_make.h new file mode 100644 index 000000000..c866572b2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_make.h @@ -0,0 +1,135 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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, + asn1_class asn1class, + asn1_tagnum tagnum, + 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, asn1_class asn1class, + asn1_construction construction, + asn1_tagnum tagnum, + 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, + asn1_class asn1class, + asn1_construction construction, + 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-7/src/lib/krb5/asn.1/asn1_misc.c b/krb5-1-7/src/lib/krb5/asn.1/asn1_misc.c new file mode 100644 index 000000000..c357f60c2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_misc.c @@ -0,0 +1,38 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/krb5/asn.1/asn1_misc.h b/krb5-1-7/src/lib/krb5/asn.1/asn1_misc.h new file mode 100644 index 000000000..ca9d57999 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1_misc.h @@ -0,0 +1,40 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/krb5/asn.1/asn1buf.c b/krb5-1-7/src/lib/krb5/asn.1/asn1buf.c new file mode 100644 index 000000000..8985140d4 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1buf.c @@ -0,0 +1,384 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* 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" +#include +#include "asn1_get.h" + +#ifdef USE_VALGRIND +#include +#else +#define VALGRIND_CHECK_READABLE(PTR,SIZE) ((void)0) +#endif + +#if !defined(__GNUC__) || defined(CONFIG_SMALL) +/* Declare private procedures as static if they're not used for inline + expansion of other stuff elsewhere. */ +static unsigned int asn1buf_free(const asn1buf *); +static asn1_error_code asn1buf_ensure_space(asn1buf *, unsigned int); +static asn1_error_code asn1buf_expand(asn1buf *, unsigned int); +#endif + +#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) +{ + if (buf->next > buf->bound + 1) return ASN1_OVERRUN; + subbuf->base = subbuf->next = buf->next; + if (!indef) { + if (length > (size_t)(buf->bound + 1 - buf->next)) return ASN1_OVERRUN; + subbuf->bound = subbuf->base + length - 1; + } 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 <= (size_t)(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 <= (size_t)(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; +} + +void asn1buf_destroy(asn1buf **buf) +{ + if (*buf != NULL) { + free((*buf)->base); + free(*buf); + *buf = NULL; + } +} + +#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_bytestring(asn1buf *buf, const unsigned int len, const void *sv) +{ + asn1_error_code retval; + unsigned int length; + const char *s = sv; + + retval = asn1buf_ensure_space(buf,len); + if (retval) return retval; + VALGRIND_CHECK_READABLE(sv, len); + for (length=1; length<=len; length++,(buf->next)++) + *(buf->next) = (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) +{ + unsigned int i; + + if (buf->next > buf->bound + 1) return ASN1_OVERRUN; + if (len > (size_t)(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; inext)[i]; + buf->next += len; + return 0; +} + +asn1_error_code asn1buf_remove_charstring(asn1buf *buf, const unsigned int len, char **s) +{ + unsigned int i; + + if (buf->next > buf->bound + 1) return ASN1_OVERRUN; + if (len > (size_t)(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; inext)[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) +{ + unsigned int i; + krb5_data *d; + + *code = NULL; + + d = calloc(1, sizeof(krb5_data)); + if (d == NULL) + return ENOMEM; + d->length = asn1buf_len(buf); + d->data = malloc(d->length + 1); + if (d->data == NULL) { + free(d); + return ENOMEM; + } + for (i=0; i < d->length; i++) + d->data[i] = buf->base[d->length - i - 1]; + d->data[d->length] = '\0'; + d->magic = KV5M_DATA; + *code = d; + 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) +{ + free(*s); + if (buf == NULL) { + *s = strdup(""); + if (*s == NULL) return ENOMEM; + } else if (buf->base == NULL) { + *s = strdup(""); + if (*s == NULL) return ENOMEM; + } else { + unsigned int length = asn1buf_len(buf); + unsigned int i; + + *s = calloc(length+1, sizeof(char)); + if (*s == NULL) return ENOMEM; + (*s)[length] = '\0'; + for (i=0; ibase)[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')) + + free(*s); + + if (buf == NULL) { + *s = strdup(""); + if (*s == NULL) return ENOMEM; + } else if (buf->base == NULL) { + *s = strdup(""); + if (*s == NULL) return ENOMEM; + } 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 */ + +static int asn1buf_size(const asn1buf *buf) +{ + if (buf == NULL || buf->base == NULL) return 0; + return buf->bound - buf->base + 1; +} + +#undef asn1buf_free +unsigned 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) +{ + unsigned int avail = asn1buf_free(buf); + if (avail >= amount) + return 0; + return asn1buf_expand(buf, amount-avail); +} + +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; + + buf->base = realloc(buf->base, + (asn1buf_size(buf)+inc) * sizeof(asn1_octet)); + if (buf->base == NULL) return ENOMEM; /* XXX leak */ + 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-7/src/lib/krb5/asn.1/asn1buf.h b/krb5-1-7/src/lib/krb5/asn.1/asn1buf.h new file mode 100644 index 000000000..33affbb07 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1buf.h @@ -0,0 +1,218 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* 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 ****************/ + +#if (__GNUC__ >= 2) && !defined(CONFIG_SMALL) +unsigned 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) \ + ? 0U \ + : (unsigned int)((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. */ +#endif + +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, asn1_class Class, + asn1_tagnum lasttag, + unsigned int length, int indef, + 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. */ + +void 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)) && !defined(CONFIG_SMALL) +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_bytestring + (asn1buf *buf, const unsigned int len, const void *s); +/* requires *buf is allocated + modifies *buf + effects Inserts the contents of s (an array of length len) + into the buffer *buf, expanding the buffer if necessary. + Returns ENOMEM if memory is exhausted. */ + +#define asn1buf_insert_octetstring asn1buf_insert_bytestring +#define asn1buf_insert_charstring asn1buf_insert_bytestring + +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-7/src/lib/krb5/asn.1/asn1glue.h b/krb5-1-7/src/lib/krb5/asn.1/asn1glue.h new file mode 100644 index 000000000..48cdc7429 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/asn1glue.h @@ -0,0 +1,47 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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-7/src/lib/krb5/asn.1/deps b/krb5-1-7/src/lib/krb5/asn.1/deps new file mode 100644 index 000000000..5ff7a7f3f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/deps @@ -0,0 +1,125 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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_k_encode.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-7/src/lib/krb5/asn.1/krb5_decode.c b/krb5-1-7/src/lib/krb5/asn.1/krb5_decode.c new file mode 100644 index 000000000..7a08ec888 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/krb5_decode.c @@ -0,0 +1,1330 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/krb5_decode.c + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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(type)\ +asn1_error_code retval;\ +asn1buf buf;\ +type rep = NULL;\ +\ +*repptr = NULL;\ +retval = asn1buf_wrap_data(&buf,code);\ +if (retval) return retval + +#define setup_no_tagnum(type)\ +asn1_class asn1class;\ +asn1_construction construction;\ +setup_buf_only(type) + +#define setup_no_length(type)\ +asn1_tagnum tagnum;\ +setup_no_tagnum(type) + +#define setup(type)\ +unsigned int length;\ +setup_no_length(type) + +/* 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)\ +var = calloc(1,sizeof(*var));\ +if ((var) == NULL) clean_return(ENOMEM) + +/* + * Allocate a principal and initialize enough fields for + * krb5_free_principal to have defined behavior. + */ +#define alloc_principal(var) \ + alloc_field(var); \ + var->realm.data = NULL; \ + var->data = NULL + +/* 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_from_buf(buf) \ +{ taginfo t2; \ + retval = asn1_get_tag_2(&(buf), &t2); \ + if (retval) clean_return(retval); \ + asn1class = t2.asn1class; \ + construction = t2.construction; \ + tagnum = t2.tagnum; \ + indef = t2.indef; \ + taglen = t2.length; \ +} +#define next_tag() next_tag_from_buf(subbuf) + + +static asn1_error_code +asn1_get_eoc_tag (asn1buf *buf) +{ + asn1_error_code retval; + taginfo t; + + retval = asn1_get_tag_2(buf, &t); + if (retval) + return retval; + if (t.asn1class != UNIVERSAL || t.tagnum || t.indef) + return ASN1_MISSING_EOC; + return 0; +} + +#define get_eoc() \ +{ \ + retval = asn1_get_eoc_tag(&subbuf); \ + if (retval) clean_return(retval); \ +} + +/* 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() + +/* + * error_if_bad_tag + * + * Checks that the next tag is the expected one; returns with an error + * if not. + */ +#define error_if_bad_tag(tagexpect) \ + if (tagnum != (tagexpect)) { clean_return ((tagnum < (tagexpect)) ? ASN1_MISPLACED_FIELD : ASN1_MISSING_FIELD); } + +/* decode a field (<[UNIVERSAL id]> ) + check that the id number == tagexpect then + decode into var + get the next tag */ +#define get_field(var,tagexpect,decoder)\ +error_if_bad_tag(tagexpect);\ +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)\ +error_if_bad_tag(tagexpect);\ +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)\ + *repptr = rep; \ + return 0; \ +error_out: \ + if (rep) \ + cleanup_routine(rep); \ + return retval; + +#define cleanup_none()\ + *repptr = rep; \ + return 0; \ +error_out: \ + return retval; + +#define cleanup_manual()\ + *repptr = rep; \ + return 0; + +#define free_field(rep,f) free((rep)->f) +#define clear_field(rep,f) (rep)->f = 0 + +#ifndef LEAN_CLIENT +krb5_error_code +decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **repptr) +{ + setup(krb5_authenticator *); + alloc_field(rep); + clear_field(rep,subkey); + clear_field(rep,checksum); + clear_field(rep,client); + clear_field(rep,authorization_data); + + 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_principal(rep->client); + get_field(rep->client,1,asn1_decode_realm); + get_field(rep->client,2,asn1_decode_principal_name); + opt_field(rep->checksum,3,asn1_decode_checksum_ptr); + get_field(rep->cusec,4,asn1_decode_int32); + get_field(rep->ctime,5,asn1_decode_kerberos_time); + opt_field(rep->subkey,6,asn1_decode_encryption_key_ptr); + 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: + krb5_free_authenticator(NULL, rep); + return retval; +} +#endif + +krb5_error_code +KRB5_CALLCONV +krb5_decode_ticket(const krb5_data *code, krb5_ticket **repptr) +{ + return decode_krb5_ticket(code, repptr); +} + +krb5_error_code +decode_krb5_ticket(const krb5_data *code, krb5_ticket **repptr) +{ + setup(krb5_ticket *); + alloc_field(rep); + clear_field(rep,server); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); + + 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_principal(rep->server); + 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: + krb5_free_ticket(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_encryption_key(const krb5_data *code, krb5_keyblock **repptr) +{ + setup(krb5_keyblock *); + alloc_field(rep); + clear_field(rep,contents); + + { 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_manual(); +error_out: + krb5_free_keyblock(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_enc_tkt_part(const krb5_data *code, krb5_enc_tkt_part **repptr) +{ + setup(krb5_enc_tkt_part *); + alloc_field(rep); + clear_field(rep,session); + clear_field(rep,client); + clear_field(rep,transited.tr_contents.data); + clear_field(rep,caddrs); + clear_field(rep,authorization_data); + + check_apptag(3); + { begin_structure(); + get_field(rep->flags,0,asn1_decode_ticket_flags); + get_field(rep->session,1,asn1_decode_encryption_key_ptr); + alloc_principal(rep->client); + 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: + krb5_free_enc_tkt_part(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_enc_kdc_rep_part(const krb5_data *code, + krb5_enc_kdc_rep_part **repptr) +{ + taginfo t4; + setup_buf_only(krb5_enc_kdc_rep_part *); + alloc_field(rep); + + 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 **repptr) +{ + setup_no_length(krb5_kdc_rep *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,ticket); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); + + 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_manual(); +error_out: + krb5_free_kdc_rep(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_tgs_rep(const krb5_data *code, krb5_kdc_rep **repptr) +{ + setup_no_length(krb5_kdc_rep *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,ticket); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); + + 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_manual(); +error_out: + krb5_free_kdc_rep(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **repptr) +{ + setup(krb5_ap_req *); + alloc_field(rep); + clear_field(rep,ticket); + clear_field(rep,authenticator.ciphertext.data); + + 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); + get_field(rep->ticket,3,asn1_decode_ticket_ptr); + get_field(rep->authenticator,4,asn1_decode_encrypted_data); + end_structure(); + rep->magic = KV5M_AP_REQ; + } + cleanup_manual(); +error_out: + krb5_free_ap_req(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **repptr) +{ + setup(krb5_ap_rep *); + alloc_field(rep); + clear_field(rep,enc_part.ciphertext.data); + + 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_manual(); +error_out: + krb5_free_ap_rep(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_ap_rep_enc_part(const krb5_data *code, + krb5_ap_rep_enc_part **repptr) +{ + setup(krb5_ap_rep_enc_part *); + alloc_field(rep); + 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); + opt_field(rep->subkey,2,asn1_decode_encryption_key_ptr); + opt_field(rep->seq_number,3,asn1_decode_seqnum); + end_structure(); + rep->magic = KV5M_AP_REP_ENC_PART; + } + cleanup_manual(); +error_out: + krb5_free_ap_rep_enc_part(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_as_req(const krb5_data *code, krb5_kdc_req **repptr) +{ + setup_no_length(krb5_kdc_req *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,server); + clear_field(rep,ktype); + clear_field(rep,addresses); + clear_field(rep,authorization_data.ciphertext.data); + clear_field(rep,unenc_authdata); + clear_field(rep,second_ticket); + clear_field(rep, kdc_state); + + 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_manual(); +error_out: + krb5_free_kdc_req(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_tgs_req(const krb5_data *code, krb5_kdc_req **repptr) +{ + setup_no_length(krb5_kdc_req *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,server); + clear_field(rep,ktype); + clear_field(rep,addresses); + clear_field(rep,authorization_data.ciphertext.data); + clear_field(rep,unenc_authdata); + clear_field(rep,second_ticket); + clear_field(rep, kdc_state); + + 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_manual(); +error_out: + krb5_free_kdc_req(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **repptr) +{ + setup_buf_only(krb5_kdc_req *); + alloc_field(rep); + + 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 **repptr, + krb5_data *body) +{ + krb5_data tmpbody; + setup(krb5_safe *); + alloc_field(rep); + clear_field(rep,user_data.data); + clear_field(rep,r_address); + clear_field(rep,s_address); + 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); + get_field(rep->checksum,3,asn1_decode_checksum_ptr); + rep->magic = KV5M_SAFE; + end_structure(); + } + if (body != NULL) + *body = tmpbody; + cleanup_manual(); +error_out: + krb5_free_safe(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_safe(const krb5_data *code, krb5_safe **repptr) +{ + return decode_krb5_safe_with_body(code, repptr, NULL); +} + +krb5_error_code +decode_krb5_priv(const krb5_data *code, krb5_priv **repptr) +{ + setup(krb5_priv *); + alloc_field(rep); + clear_field(rep,enc_part.ciphertext.data); + + 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_manual(); +error_out: + krb5_free_priv(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_part **repptr) +{ + setup(krb5_priv_enc_part *); + alloc_field(rep); + clear_field(rep,user_data.data); + 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); + get_field(rep->s_address,4,asn1_decode_host_address_ptr); + opt_field(rep->r_address,5,asn1_decode_host_address_ptr); + rep->magic = KV5M_PRIV_ENC_PART; + end_structure(); + } + cleanup_manual(); +error_out: + krb5_free_priv_enc_part(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_cred(const krb5_data *code, krb5_cred **repptr) +{ + setup(krb5_cred *); + alloc_field(rep); + clear_field(rep,tickets); + clear_field(rep,enc_part.ciphertext.data); + + 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_manual(); +error_out: + krb5_free_cred(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_enc_cred_part(const krb5_data *code, krb5_cred_enc_part **repptr) +{ + setup(krb5_cred_enc_part *); + alloc_field(rep); + clear_field(rep,r_address); + clear_field(rep,s_address); + clear_field(rep,ticket_info); + + 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); + opt_field(rep->s_address,4,asn1_decode_host_address_ptr); + opt_field(rep->r_address,5,asn1_decode_host_address_ptr); + rep->magic = KV5M_CRED_ENC_PART; + end_structure(); + } + cleanup_manual(); +error_out: + /* Despite the name, krb5_free_cred_enc_part is contents only. */ + krb5_free_cred_enc_part(NULL, rep); + free(rep); + return retval; +} + + +krb5_error_code +decode_krb5_error(const krb5_data *code, krb5_error **repptr) +{ + setup(krb5_error *); + alloc_field(rep); + clear_field(rep,server); + clear_field(rep,client); + clear_field(rep,text.data); + clear_field(rep,e_data.data); + + 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_principal(rep->client); } + opt_field(rep->client,7,asn1_decode_realm); + opt_field(rep->client,8,asn1_decode_principal_name); + alloc_principal(rep->server); + 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: + krb5_free_error(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_authdata(const krb5_data *code, krb5_authdata ***repptr) +{ + setup_buf_only(krb5_authdata **); + 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 **repptr) +{ + setup_buf_only(passwd_phrase_element *); + alloc_field(rep); + 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 **repptr) +{ + setup(krb5_pwd_data *); + alloc_field(rep); + clear_field(rep,element); + { 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_manual(); +error_out: + krb5_free_pwd_data(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_padata_sequence(const krb5_data *code, krb5_pa_data ***repptr) +{ + setup_buf_only(krb5_pa_data **); + 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 **repptr) +{ + setup(krb5_alt_method *); + alloc_field(rep); + clear_field(rep,data); + { 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_manual(); +error_out: + krb5_free_alt_method(NULL, rep); + return retval; +} + +krb5_error_code +decode_krb5_etype_info(const krb5_data *code, krb5_etype_info_entry ***repptr) +{ + setup_buf_only(krb5_etype_info_entry **); + 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 ***repptr) +{ + setup_buf_only(krb5_etype_info_entry **); + 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 **repptr) +{ + setup_buf_only(krb5_enc_data *); + alloc_field(rep); + + 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 **repptr) +{ + setup(krb5_pa_enc_ts *); + alloc_field(rep); + { 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 **repptr) +{ + setup_buf_only(krb5_sam_challenge *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_sam_challenge_2 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_sam_challenge_2_body *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_sam_key *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_enc_sam_response_enc *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_enc_sam_response_enc_2 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_sam_response *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_sam_response_2 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_predicted_sam_response *); /* preallocated */ + alloc_field(rep); + + retval = asn1_decode_predicted_sam_response(&buf,rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +decode_krb5_setpw_req(const krb5_data *code, krb5_data **repptr, + krb5_principal *principal) +{ + setup_buf_only(krb5_data *); + alloc_field(rep); + *principal = NULL; + + retval = asn1_decode_setpw_req(&buf, rep, principal); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +decode_krb5_pa_for_user(const krb5_data *code, krb5_pa_for_user **repptr) +{ + setup_buf_only(krb5_pa_for_user *); + alloc_field(rep); + + retval = asn1_decode_pa_for_user(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +decode_krb5_pa_pac_req(const krb5_data *code, krb5_pa_pac_req **repptr) +{ + setup_buf_only(krb5_pa_pac_req *); + alloc_field(rep); + + retval = asn1_decode_pa_pac_req(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +decode_krb5_etype_list(const krb5_data *code, krb5_etype_list **repptr) +{ + setup_buf_only(krb5_etype_list *); + alloc_field(rep); + + retval = asn1_decode_sequence_of_enctype(&buf, &rep->length, &rep->etypes); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_pa_fx_fast_request +(const krb5_data *code, krb5_fast_armored_req **repptr) +{ + setup(krb5_fast_armored_req *); + alloc_field(rep); + clear_field(rep, armor); + { + int indef; + unsigned int taglen; + next_tag_from_buf(buf); + if (tagnum != 0) + clean_return(ASN1_BAD_ID); + } + {begin_structure(); + opt_field(rep->armor, 0, asn1_decode_fast_armor_ptr); + get_field(rep->req_checksum, 1, asn1_decode_checksum); + get_field(rep->enc_part, 2, asn1_decode_encrypted_data); + end_structure();} + rep->magic = KV5M_FAST_ARMORED_REQ; + cleanup(free); +} + +krb5_error_code decode_krb5_fast_req +(const krb5_data *code, krb5_fast_req **repptr) +{ + setup(krb5_fast_req *); + alloc_field(rep); + alloc_field(rep->req_body); + clear_field(rep, req_body->padata); + {begin_structure(); + get_field(rep->fast_options, 0, asn1_decode_krb5_flags); + opt_field(rep->req_body->padata, 1, asn1_decode_sequence_of_pa_data); + get_field(*(rep->req_body), 2, asn1_decode_kdc_req_body); + end_structure(); } + rep->magic = KV5M_FAST_REQ; + cleanup_manual(); + error_out: + if (rep) { + if (rep->req_body) + krb5_free_kdc_req(0, rep->req_body); + free(rep); + } + return retval; +} + +krb5_error_code decode_krb5_fast_response +(const krb5_data *code, krb5_fast_response **repptr) +{ + setup(krb5_fast_response *); + + alloc_field(rep); + clear_field(rep, finished); + clear_field(rep, padata); + clear_field(rep,strengthen_key); + {begin_structure(); + get_field(rep->padata, 0, asn1_decode_sequence_of_pa_data); + opt_field(rep->strengthen_key, 1, asn1_decode_encryption_key_ptr); + opt_field(rep->finished, 2, asn1_decode_fast_finished_ptr); + get_field(rep->nonce, 3, asn1_decode_int32); + end_structure(); } + rep->magic = KV5M_FAST_RESPONSE; + cleanup(free); +} + +krb5_error_code decode_krb5_pa_fx_fast_reply +(const krb5_data *code, krb5_enc_data **repptr) +{ + setup(krb5_enc_data *); + alloc_field(rep); + { + int indef; + unsigned int taglen; + next_tag_from_buf(buf); + if (tagnum != 0) + clean_return(ASN1_BAD_ID); + } + {begin_structure(); + get_field(*rep, 0, asn1_decode_encrypted_data); + end_structure(); + } + + cleanup(free); +} + + +#ifndef DISABLE_PKINIT +krb5_error_code +decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **repptr) +{ + setup_buf_only(krb5_pa_pk_as_req *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_pa_pk_as_req_draft9 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_pa_pk_as_rep *); + alloc_field(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 **repptr) +{ + setup_buf_only(krb5_pa_pk_as_rep_draft9 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_auth_pack *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_auth_pack_draft9 *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_kdc_dh_key_info *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_principal_data *); + alloc_field(rep); + + 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 **repptr) +{ + setup_buf_only(krb5_reply_key_pack *); + alloc_field(rep); + + retval = asn1_decode_reply_key_pack(&buf, rep); + if (retval) + goto error_out; + + cleanup(free); +} + +krb5_error_code +decode_krb5_reply_key_pack_draft9(const krb5_data *code, + krb5_reply_key_pack_draft9 **repptr) +{ + setup_buf_only(krb5_reply_key_pack_draft9 *); + alloc_field(rep); + + retval = asn1_decode_reply_key_pack_draft9(&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 ***repptr) +{ + setup_buf_only(krb5_external_principal_identifier **); + 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 ***repptr) +{ + setup_buf_only(krb5_algorithm_identifier **); + retval = asn1_decode_sequence_of_algorithm_identifier(&buf, &rep); + if (retval) clean_return(retval); + + cleanup(free); +} +#endif /* DISABLE_PKINIT */ + +krb5_error_code +decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***repptr) +{ + setup_buf_only(krb5_typed_data **); + retval = asn1_decode_sequence_of_typed_data(&buf, &rep); + if (retval) clean_return(retval); + + cleanup(free); +} diff --git a/krb5-1-7/src/lib/krb5/asn.1/krb5_encode.c b/krb5-1-7/src/lib/krb5/asn.1/krb5_encode.c new file mode 100644 index 000000000..5834e8ae8 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/krb5_encode.c @@ -0,0 +1,174 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * src/lib/krb5/asn.1/krb5_encode.c + * + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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) ****************/ + +/* 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;\ + unsigned int length, sum = 0;\ + asn1buf *buf=NULL;\ + krb5_data *tmpcode;\ +\ + *code = NULL;\ +\ + if (rep == NULL) return ASN1_MISSING_FIELD;\ +\ + retval = asn1buf_create(&buf);\ + if (retval) return retval + +/* produce the final output and clean up the workspace */ +#define krb5_cleanup()\ + retval = asn12krb5_buf(buf,&tmpcode);\ +error:\ + asn1buf_destroy(&buf);\ + if (retval)\ + return retval;\ + *code = tmpcode;\ + return 0 + +#ifndef DISABLE_PKINIT +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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + 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) goto error; + sum += length; + krb5_cleanup(); +} +#endif /* DISABLE_PKINIT */ + +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) goto error; + sum += length; + krb5_cleanup(); +} + diff --git a/krb5-1-7/src/lib/krb5/asn.1/krbasn1.h b/krb5-1-7/src/lib/krb5/asn.1/krbasn1.h new file mode 100644 index 000000000..985381a25 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/krbasn1.h @@ -0,0 +1,76 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +#ifndef __KRBASN1_H__ +#define __KRBASN1_H__ + +#include "k5-int.h" +#include +#include +#include /* For INT_MAX */ +#ifdef HAVE_STDLIB_H +#include +#endif + +/* + * 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 INT64_TYPE asn1_intmax; +typedef UINT64_TYPE asn1_uintmax; + +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_BOOLEAN 1 +#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-7/src/lib/krb5/asn.1/ldap_key_seq.c b/krb5-1-7/src/lib/krb5/asn.1/ldap_key_seq.c new file mode 100644 index 000000000..2807a5101 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/asn.1/ldap_key_seq.c @@ -0,0 +1,386 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* ... 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 +#include + +#include "krbasn1.h" +#include "asn1_encode.h" +#include "asn1_decode.h" +#include "asn1_make.h" +#include "asn1_get.h" +#include "asn1_k_encode.h" + +#ifdef ENABLE_LDAP + +/************************************************************************/ +/* Encode the Principal's keys */ +/************************************************************************/ + +/* Imports from asn1_k_encode.c. + XXX Must be manually synchronized for now. */ +IMPORT_TYPE(octetstring, unsigned char *); +IMPORT_TYPE(int32, krb5_int32); + +DEFINTTYPE(int16, krb5_int16); +DEFINTTYPE(ui_2, krb5_ui_2); + +static const struct field_info krbsalt_fields[] = { + FIELDOF_NORM(krb5_key_data, int16, key_data_type[1], 0), + FIELDOF_OPTSTRINGL(krb5_key_data, octetstring, key_data_contents[1], + ui_2, key_data_length[1], 1, 1), +}; +static unsigned int optional_krbsalt (const void *p) +{ + const krb5_key_data *k = p; + unsigned int optional = 0; + + if (k->key_data_length[1] > 0) + optional |= (1u << 1); + + return optional; +} +DEFSEQTYPE(krbsalt, krb5_key_data, krbsalt_fields, optional_krbsalt); +static const struct field_info encryptionkey_fields[] = { + FIELDOF_NORM(krb5_key_data, int16, key_data_type[0], 0), + FIELDOF_STRINGL(krb5_key_data, octetstring, key_data_contents[0], + ui_2, key_data_length[0], 1), +}; +DEFSEQTYPE(encryptionkey, krb5_key_data, encryptionkey_fields, 0); + +static const struct field_info key_data_fields[] = { + FIELDOF_ENCODEAS(krb5_key_data, krbsalt, 0), + FIELDOF_ENCODEAS(krb5_key_data, encryptionkey, 1), +#if 0 /* We don't support this field currently. */ + FIELDOF_blah(krb5_key_data, s2kparams, ...), +#endif +}; +DEFSEQTYPE(key_data, krb5_key_data, key_data_fields, 0); +DEFPTRTYPE(ptr_key_data, key_data); + +DEFFIELDTYPE(key_data_kvno, krb5_key_data, + FIELDOF_NORM(krb5_key_data, int16, key_data_kvno, -1)); +DEFPTRTYPE(ptr_key_data_kvno, key_data_kvno); + +static const struct field_info ldap_key_seq_fields[] = { + FIELD_INT_IMM(1, 0), + FIELD_INT_IMM(1, 1), + FIELDOF_NORM(ldap_seqof_key_data, ptr_key_data_kvno, key_data, 2), + FIELDOF_NORM(ldap_seqof_key_data, int32, mkvno, 3), /* mkvno */ + FIELDOF_SEQOF_LEN(ldap_seqof_key_data, ptr_key_data, key_data, n_key_data, + int16, 4), +}; +DEFSEQTYPE(ldap_key_seq, ldap_seqof_key_data, ldap_key_seq_fields, 0); + +/* Export a function to do the whole encoding. */ +MAKE_FULL_ENCODER(krb5int_ldap_encode_sequence_of_keys, ldap_key_seq); + +/************************************************************************/ +/* Decode the Principal's keys */ +/************************************************************************/ + +#define cleanup(err) \ + { \ + ret = err; \ + goto last; \ + } + +#define checkerr \ + if (ret != 0) \ + goto last + +#define safe_syncbuf(outer,inner,buflen) \ + 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, buflen); + *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, buflen); + *buf = tmp; + +last: + return ret; +} +#endif + +static asn1_error_code +decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag, + unsigned 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, buflen); + *buf = tmp; + +last: + if (ret != 0) + free (*val); + return ret; +} + +static asn1_error_code asn1_decode_key(asn1buf *buf, krb5_key_data *key) +{ + int full_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; + full_buflen = length; + ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr; + + asn1_get_tag_2(&subbuf, &t); + /* Salt */ + if (t.tagnum == 0) { + int salt_buflen; + asn1buf slt; + long keytype; + unsigned int keylen; + + key->key_data_ver = 2; + asn1_get_sequence(&subbuf, &length, &seqindef); + salt_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; + } else + keylen = 0; + safe_syncbuf (&subbuf, &slt, salt_buflen); + 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 key_buflen; + asn1buf kbuf; + long lval; + unsigned int ival; + + if (t.tagnum != 1) + cleanup (ASN1_MISSING_FIELD); + + ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr; + key_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, key_buflen); + } + + safe_syncbuf (buf, &subbuf, full_buflen); + +last: + if (ret != 0) { + free (key->key_data_contents[0]); + key->key_data_contents[0] = NULL; + free (key->key_data_contents[1]); + key->key_data_contents[1] = NULL; + } + return ret; +} + +krb5_error_code krb5int_ldap_decode_sequence_of_keys (krb5_data *in, + ldap_seqof_key_data **rep) +{ + ldap_seqof_key_data *repval; + 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; + + repval = calloc(1,sizeof(ldap_seqof_key_data)); + *rep = repval; + out = &repval->key_data; + n_key_data = &repval->n_key_data; + mkvno = &repval->mkvno; + + *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, seq_buflen; + asn1buf keyseq; + if (t.tagnum != 4) + cleanup (ASN1_MISSING_FIELD); + ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr; + seq_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, seq_buflen); + } + + /* + * 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++) { + free ((*out)[i].key_data_contents[0]); + free ((*out)[i].key_data_contents[1]); + } + free (*out); + *out = NULL; + } + + return ret; +} +#endif diff --git a/krb5-1-7/src/lib/krb5/ccache/Makefile.in b/krb5-1-7/src/lib/krb5/ccache/Makefile.in new file mode 100644 index 000000000..5dcf2adf6 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/Makefile.in @@ -0,0 +1,115 @@ +thisconfigdir=../../.. +myfulldir=lib/krb5/ccache +mydir=lib/krb5/ccache +BUILDTOP=$(REL)..$(S)..$(S).. +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) + +EXTRADEPSRCS= \ + $(srcdir)/t_cc.c \ + $(srcdir)/t_cccursor.c + +##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 t_cccursor + KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) ./t_cc + KRB5_CONFIG=$(srcdir)/../krb/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) ./t_cccursor + +clean-unix:: + $(RM) t_cc t_cc.o t_cccursor t_cccursor.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@ + diff --git a/krb5-1-7/src/lib/krb5/ccache/cc-int.h b/krb5-1-7/src/lib/krb5/ccache/cc-int.h new file mode 100644 index 000000000..84b100286 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cc-int.h @@ -0,0 +1,116 @@ +/* + * 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); + +krb5_error_code krb5int_random_string (krb5_context, char *, unsigned int); + +/* + * 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); + +/* reentrant mutex used by krb5_cc_* functions */ +typedef struct _k5_cc_mutex { + k5_mutex_t lock; + krb5_context owner; + krb5_int32 refcount; +} k5_cc_mutex; + +#define K5_CC_MUTEX_PARTIAL_INITIALIZER \ + { K5_MUTEX_PARTIAL_INITIALIZER, NULL, 0 } + +krb5_error_code +k5_cc_mutex_init(k5_cc_mutex *m); + +krb5_error_code +k5_cc_mutex_finish_init(k5_cc_mutex *m); + +#define k5_cc_mutex_destroy(M) \ +k5_mutex_destroy(&(M)->lock); + +void +k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m); + +void +k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m); + +krb5_error_code +k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m); + +krb5_error_code +k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m); + +extern k5_cc_mutex krb5int_mcc_mutex; +extern k5_cc_mutex krb5int_krcc_mutex; +extern k5_cc_mutex krb5int_cc_file_mutex; + +#ifdef USE_CCAPI_V3 +extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock +(krb5_context context); + +extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock +(krb5_context context); +#endif + +krb5_error_code +k5_cc_mutex_force_unlock(k5_cc_mutex *m); + +krb5_error_code +k5_cccol_force_unlock(void); + +#endif /* __KRB5_CCACHE_H__ */ diff --git a/krb5-1-7/src/lib/krb5/ccache/cc_file.c b/krb5-1-7/src/lib/krb5/ccache/cc_file.c new file mode 100644 index 000000000..23ece3e12 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cc_file.c @@ -0,0 +1,2639 @@ +/* + * lib/krb5/ccache/cc_file.c + * + * Copyright 1990,1991,1992,1993,1994,2000,2004,2007 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 "cc-int.h" + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#if !defined(_WIN32) +#include +#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); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_new + (krb5_context context, krb5_cc_ptcursor *cursor); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_next + (krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_free + (krb5_context context, krb5_cc_ptcursor *cursor); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_last_change_time + (krb5_context context, krb5_ccache id, krb5_timestamp *change_time); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_lock + (krb5_context context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_fcc_unlock + (krb5_context context, krb5_ccache id); + + +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); +static krb5_error_code krb5_fcc_data_last_change_time + (krb5_context context, struct _krb5_fcc_data *data, + krb5_timestamp *change_time); + + +#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_cc_mutex 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_cc_mutex krb5int_cc_file_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER; +static struct fcc_set *fccs = NULL; + +/* Iterator over file caches. */ +struct krb5_fcc_ptcursor_data { + struct fcc_set *cur; +}; + +/* 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_cc_mutex_assert_locked(CONTEXT, &((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_cc_mutex_unlock(CONTEXT, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &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_ 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_cc_mutex_assert_locked(context, &((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(krb5_princ_realm(context, tmpprinc)->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_cc_mutex_assert_locked(context, &((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); + *addrs = 0; + 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_cc_mutex_assert_locked(context, &((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) { + free(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_cc_mutex_assert_locked(context, &((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) { + free(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_cc_mutex_assert_locked(context, &((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) { + free(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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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); + *a = NULL; + 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_cc_mutex_assert_locked(context, &((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) { + free(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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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) +{ + return krb5_fcc_store_ui_4(context, id, (krb5_ui_4) i); +} + +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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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; idata)->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_cc_mutex_assert_locked(context, &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 = &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_cc_mutex_assert_locked(context, &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) { + switch (errno) { + case ENOENT: + retval = KRB5_FCC_NOFILE; + krb5_set_error_message(context, retval, + "Credentials cache file '%s' not found", + data->filename); + return retval; + default: + return krb5_fcc_interpret (context, errno); + } + } + set_cloexec_fd(f); + + 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_cc_mutex_assert_locked(context, &((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_cc_mutex_assert_locked(context, &((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_cc_mutex_lock(context, &((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_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock); + return kret; + } + } +#endif + kret = krb5_fcc_store_principal(context, id, princ); + + MAYBE_CLOSE(context, id, kret); + k5_cc_mutex_unlock(context, &((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_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_mutex_assert_unlocked(context, &data->lock); + free(data->filename); + zap(data->buf, sizeof(data->buf)); + if (data->file >= 0) { + kerr = k5_cc_mutex_lock(context, &data->lock); + if (kerr) + return kerr; + krb5_fcc_close_file(context, data); + k5_cc_mutex_unlock(context, &data->lock); + } + k5_cc_mutex_destroy(&data->lock); + free(data); + } else + k5_cc_mutex_unlock(context, &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); + free(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_cc_mutex_lock(context, &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; + } + set_cloexec_fd(ret); + 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_cc_mutex_unlock(context, &data->lock); + dereference(context, data); + free(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_cc_mutex_lock(context, &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_cc_mutex_lock(context, &data->lock); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + return kret; + } + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + } else { + data = malloc(sizeof(krb5_fcc_data)); + if (data == NULL) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + return KRB5_CC_NOMEM; + } + data->filename = strdup(residual); + if (data->filename == NULL) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + free(data); + return KRB5_CC_NOMEM; + } + kret = k5_cc_mutex_init(&data->lock); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + free(data->filename); + free(data); + return kret; + } + kret = k5_cc_mutex_lock(context, &data->lock); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_mutex_unlock(context, &data->lock); + k5_cc_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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + } + + k5_cc_mutex_assert_locked(context, &data->lock); + k5_cc_mutex_unlock(context, &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_cc_mutex_lock(context, &data->lock); + if (kret) + return kret; + + fcursor = (krb5_fcc_cursor *) malloc(sizeof(krb5_fcc_cursor)); + if (fcursor == NULL) { + k5_cc_mutex_unlock(context, &data->lock); + return KRB5_CC_NOMEM; + } + if (OPENCLOSE(id)) { + kret = krb5_fcc_open_file(context, id, FCC_OPEN_RDONLY); + if (kret) { + free(fcursor); + k5_cc_mutex_unlock(context, &data->lock); + return kret; + } + } + + /* Make sure we start reading right after the primary principal */ + kret = krb5_fcc_skip_header(context, id); + if (kret) { + free(fcursor); + goto done; + } + kret = krb5_fcc_skip_principal(context, id); + if (kret) { + free(fcursor); + goto done; + } + + fcursor->pos = fcc_lseek(data, (off_t) 0, SEEK_CUR); + *cursor = (krb5_cc_cursor) fcursor; + +done: + MAYBE_CLOSE(context, id, kret); + k5_cc_mutex_unlock(context, &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_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &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); + +lose: + MAYBE_CLOSE (context, id, kret); + k5_cc_mutex_unlock(context, &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); */ + free((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_cc_mutex_lock(context, &krb5int_cc_file_mutex); + if (kret) + return kret; + + (void) snprintf(scratch, sizeof(scratch), "%sXXXXXX", TKT_ROOT); + ret = mkstemp(scratch); + if (ret == -1) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + return krb5_fcc_interpret(context, errno); + } + set_cloexec_fd(ret); + + /* Allocate memory */ + data = (krb5_pointer) malloc(sizeof(krb5_fcc_data)); + if (data == NULL) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + close(ret); + unlink(scratch); + return KRB5_CC_NOMEM; + } + + data->filename = strdup(scratch); + if (data->filename == NULL) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + free(data); + close(ret); + unlink(scratch); + return KRB5_CC_NOMEM; + } + + kret = k5_cc_mutex_init(&data->lock); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + free(data->filename); + free(data); + close(ret); + unlink(scratch); + return kret; + } + kret = k5_cc_mutex_lock(context, &data->lock); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_mutex_unlock(context, &data->lock); + k5_cc_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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + + k5_cc_mutex_assert_locked(context, &data->lock); + k5_cc_mutex_unlock(context, &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_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_cc_mutex_unlock(context, &data->lock); + k5_cc_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_cc_mutex_lock(context, &((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_cc_mutex_unlock(context, &((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_cc_mutex_lock(context, &((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_cc_mutex_unlock(context, &((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_cc_mutex_unlock(context, &((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_cc_mutex_lock(context, &((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_cc_mutex_unlock(context, &((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_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock); + if (ret) + return ret; + *flags = ((krb5_fcc_data *) id->data)->flags; + k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_fcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor) +{ + krb5_error_code ret = 0; + krb5_cc_ptcursor n = NULL; + struct krb5_fcc_ptcursor_data *cdata = NULL; + + *cursor = NULL; + + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + n->ops = &krb5_fcc_ops; + cdata = malloc(sizeof(struct krb5_fcc_ptcursor_data)); + if (cdata == NULL) { + ret = ENOMEM; + goto errout; + } + n->data = cdata; + ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); + if (ret) + goto errout; + cdata->cur = fccs; + ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + if (ret) + goto errout; + +errout: + if (ret) { + krb5_fcc_ptcursor_free(context, &n); + } + *cursor = n; + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_fcc_ptcursor_next(krb5_context context, + krb5_cc_ptcursor cursor, + krb5_ccache *ccache) +{ + krb5_error_code ret = 0; + struct krb5_fcc_ptcursor_data *cdata = NULL; + krb5_ccache n; + + *ccache = NULL; + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + + cdata = cursor->data; + + ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); + if (ret) + goto errout; + + if (cdata->cur == NULL) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + free(n); + n = NULL; + goto errout; + } + + n->ops = &krb5_fcc_ops; + n->data = cdata->cur->data; + cdata->cur->refcount++; + + cdata->cur = cdata->cur->next; + + ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + if (ret) + goto errout; +errout: + if (ret && n != NULL) { + free(n); + n = NULL; + } + *ccache = n; + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_fcc_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; +} + +/* + * Modifies: + * change_time + * + * Effects: + * Returns the timestamp of id's file modification date. + * If an error occurs, change_time is set to 0. + */ +static krb5_error_code KRB5_CALLCONV +krb5_fcc_last_change_time(krb5_context context, krb5_ccache id, + krb5_timestamp *change_time) +{ + krb5_error_code kret = KRB5_OK; + krb5_fcc_data *data = (krb5_fcc_data *) id->data; + + kret = krb5_fcc_data_last_change_time(context, data, change_time); + + return kret; +} + +static krb5_error_code KRB5_CALLCONV krb5_fcc_lock(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_fcc_data *data = (krb5_fcc_data *) id->data; + ret = k5_cc_mutex_lock(context, &data->lock); + return ret; +} + +static krb5_error_code KRB5_CALLCONV krb5_fcc_unlock(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_fcc_data *data = (krb5_fcc_data *) id->data; + ret = k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +static krb5_error_code +krb5_fcc_data_last_change_time(krb5_context context, krb5_fcc_data *data, + krb5_timestamp *change_time) +{ + krb5_error_code kret = KRB5_OK; + register int ret; + + struct stat buf; + + *change_time = 0; + + kret = k5_cc_mutex_lock(context, &data->lock); + if (kret) { + return kret; + } + + ret = stat(data->filename, &buf); + if (ret == -1) { + kret = krb5_fcc_interpret(context, errno); + } else { + *change_time = (krb5_timestamp) buf.st_mtime; + } + + k5_cc_mutex_unlock(context, &data->lock); + + return kret; +} + +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, + krb5_fcc_ptcursor_new, + krb5_fcc_ptcursor_next, + krb5_fcc_ptcursor_free, + NULL, /* move */ + krb5_fcc_last_change_time, + NULL, /* wasdefault */ + krb5_fcc_lock, + krb5_fcc_unlock, +}; + +#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, + krb5_fcc_ptcursor_new, + krb5_fcc_ptcursor_next, + krb5_fcc_ptcursor_free, + NULL, /* move */ + krb5_fcc_last_change_time, + NULL, /* wasdefault */ + krb5_fcc_lock, + krb5_fcc_unlock, +}; diff --git a/krb5-1-7/src/lib/krb5/ccache/cc_keyring.c b/krb5-1-7/src/lib/krb5/ccache/cc_keyring.c new file mode 100644 index 000000000..528f43f06 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cc_keyring.c @@ -0,0 +1,2111 @@ +/* + * 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 "cc-int.h" + +#ifdef USE_KEYRING_CCACHE + +#include +#include + +#ifdef DEBUG +#define KRCC_DEBUG 1 +#endif + +#if KRCC_DEBUG +void debug_print(char *fmt, ...); /* prototype to silence warning */ +#include +#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 + * :: + */ +#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_cc_mutex 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_timestamp changetime; +} 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_cc_mutex krb5int_krcc_mutex = K5_CC_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); + +static krb5_error_code KRB5_CALLCONV krb5_krcc_last_change_time + (krb5_context, krb5_ccache, krb5_timestamp *); + +static krb5_error_code KRB5_CALLCONV krb5_krcc_lock + (krb5_context context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_krcc_unlock + (krb5_context context, krb5_ccache id); + +/* + * 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); +static void krb5_krcc_update_change_time + (krb5_krcc_data *); + +/* 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_cc_mutex_lock(context, &((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_cc_mutex_unlock(context, &((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; + + free(d->name); + k5_cc_mutex_destroy(&d->lock); + free(d); + + free(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_cc_mutex_assert_locked(context, &((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; + krb5_krcc_update_change_time(d); + + 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_cc_mutex_lock(context, &d->lock); + if (kret) + return kret; + + krb5_krcc_clearcache(context, id); + free(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_cc_mutex_unlock(context, &d->lock); + k5_cc_mutex_destroy(&d->lock); + free(d); + free(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 . + * + * 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_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &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_cc_mutex_unlock(context, &d->lock); + return KRB5_CC_IO; + } + + krcursor->numkeys = d->numkeys; + krcursor->currkey = 0; + krcursor->princ_id = d->princ_id; + + k5_cc_mutex_unlock(context, &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_cc_mutex_init(&d->lock); + if (kret) { + free(d); + return kret; + } + + d->name = strdup(name); + if (d->name == NULL) { + k5_cc_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + d->princ_id = 0; + d->ring_id = ring; + d->parent_id = parent_ring; + d->numkeys = 0; + d->changetime = 0; + krb5_krcc_update_change_time(d); + + *datapp = d; + return 0; +} + +/* + * 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_cc_mutex_lock(context, &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) { + kret = krb5int_random_string(context, uniquename, sizeof(uniquename)); + if (kret) { + k5_cc_mutex_unlock(context, &krb5int_krcc_mutex); + free(lid); + return kret; + } + + 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_cc_mutex_unlock(context, &krb5int_krcc_mutex); + return kret; + } + break; + } + } + + kret = krb5_krcc_new_data(uniquename, key, ring_id, &d); + k5_cc_mutex_unlock(context, &krb5int_krcc_mutex); + if (kret) { + free(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_cc_mutex_lock(context, &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; + krb5_krcc_update_change_time(d); + } + + errout: + if (keyname) + krb5_free_unparsed_name(context, keyname); + if (payload) + free(payload); + + k5_cc_mutex_unlock(context, &d->lock); + return kret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_krcc_last_change_time(krb5_context context, krb5_ccache id, + krb5_timestamp *change_time) +{ + krb5_error_code ret = 0; + krb5_krcc_data *data = (krb5_krcc_data *) id->data; + + *change_time = 0; + + ret = k5_cc_mutex_lock(context, &data->lock); + if (!ret) { + *change_time = data->changetime; + k5_cc_mutex_unlock(context, &data->lock); + } + + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_krcc_lock(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_krcc_data *data = (krb5_krcc_data *) id->data; + ret = k5_cc_mutex_lock(context, &data->lock); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_krcc_unlock(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_krcc_data *data = (krb5_krcc_data *) id->data; + ret = k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + + +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_cc_mutex_assert_locked(context, &((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 ? "" : 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; + krb5_krcc_update_change_time(d); + } + + 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_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &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); + free(creds->ticket.data); + cleanauthdata: + krb5_free_authdata(context, creds->authdata); + cleanaddrs: + krb5_free_addresses(context, creds->addresses); + cleanblock: + free(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(krb5_princ_realm(context, tmpprinc)->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) + free(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) + free(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]; + + kret = krb5_krcc_parse(context, id, buf, 4, bc); + if (kret) + return kret; + *i = load_32_be(buf); + 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) + free(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); + *a = NULL; + 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); + *a = NULL; + } + 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) + free(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 = load_16_be(buf); + 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) +{ + return krb5_krcc_unparse_ui_4(context, id, (krb5_ui_4) i, 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]; + + store_32_be(i, buf); + 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]; + + store_16_be(i, buf); + 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; +} + +/* + * Utility routine: called by krb5_krcc_* functions to keep + * result of krb5_krcc_last_change_time up to date. + * Value monotonically increases -- based on but not guaranteed to be actual + * system time. + */ + +static void +krb5_krcc_update_change_time(krb5_krcc_data *d) +{ + krb5_timestamp now_time = time(NULL); + d->changetime = (d->changetime >= now_time) ? + d->changetime + 1 : now_time; +} + + +/* + * 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 */ + NULL, + NULL, + NULL, + NULL, /* move */ + krb5_krcc_last_change_time, /* lastchange */ + NULL, /* wasdefault */ + krb5_krcc_lock, + krb5_krcc_unlock, +}; + +#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 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* USE_KEYRING_CCACHE */ diff --git a/krb5-1-7/src/lib/krb5/ccache/cc_memory.c b/krb5-1-7/src/lib/krb5/ccache/cc_memory.c new file mode 100644 index 000000000..2cfd60a10 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cc_memory.c @@ -0,0 +1,823 @@ +/* + * lib/krb5/ccache/cc_memory.c + * + * Copyright 1990,1991,2000,2004,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "cc-int.h" +#include + +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 *); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_last_change_time + (krb5_context, krb5_ccache, krb5_timestamp *); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_lock + (krb5_context context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_unlock + (krb5_context context, krb5_ccache id); + + +extern const krb5_cc_ops krb5_mcc_ops; +extern krb5_error_code krb5_change_cache (void); + +#define KRB5_OK 0 + +/* Individual credentials within a cache, in a linked list. */ +typedef struct _krb5_mcc_link { + struct _krb5_mcc_link *next; + krb5_creds *creds; +} krb5_mcc_link, *krb5_mcc_cursor; + +/* Per-cache data header. */ +typedef struct _krb5_mcc_data { + char *name; + k5_cc_mutex lock; + krb5_principal prin; + krb5_mcc_cursor link; + krb5_timestamp changetime; +} krb5_mcc_data; + +/* List of memory caches. */ +typedef struct krb5_mcc_list_node { + struct krb5_mcc_list_node *next; + krb5_mcc_data *cache; +} krb5_mcc_list_node; + +/* Iterator over memory caches. */ +struct krb5_mcc_ptcursor_data { + struct krb5_mcc_list_node *cur; +}; + +k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER; +static krb5_mcc_list_node *mcc_head = 0; + +static void update_mcc_change_time(krb5_mcc_data *); + +/* + * 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_data *d; + + d = (krb5_mcc_data *)id->data; + ret = k5_cc_mutex_lock(context, &d->lock); + if (ret) + return ret; + + krb5_mcc_free(context, id); + + d = (krb5_mcc_data *)id->data; + ret = krb5_copy_principal(context, princ, + &d->prin); + update_mcc_change_time(d); + + k5_cc_mutex_unlock(context, &d->lock); + 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) +{ + free(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; + free(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_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &krb5int_mcc_mutex); + + err = k5_cc_mutex_lock(context, &d->lock); + if (err) + return err; + + krb5_mcc_free(context, id); + free(d->name); + k5_cc_mutex_unlock(context, &d->lock); + k5_cc_mutex_destroy(&d->lock); + free(d); + free(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; + + err = k5_cc_mutex_lock(context, &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_cc_mutex_unlock(context, &krb5int_mcc_mutex); + return err; + } + } + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) + return KRB5_CC_NOMEM; + + lid->ops = &krb5_mcc_ops; + 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_cc_mutex_lock(context, &d->lock); + if (err) + return err; + mcursor = d->link; + k5_cc_mutex_unlock(context, &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; + + /* 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) { + retval = krb5int_copy_creds_contents(context, mcursor->creds, creds); + if (retval) + return retval; + } + *cursor = (krb5_cc_cursor)mcursor->next; + return KRB5_OK; +} + +/* + * 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_cc_mutex_init(&d->lock); + if (err) { + free(d); + return err; + } + + d->name = strdup(name); + if (d->name == NULL) { + k5_cc_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + d->link = NULL; + d->prin = NULL; + d->changetime = 0; + update_mcc_change_time(d); + + n = malloc(sizeof(krb5_mcc_list_node)); + if (n == NULL) { + free(d->name); + k5_cc_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + + n->cache = d; + n->next = mcc_head; + mcc_head = n; + + *dataptr = d; + 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 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_cc_mutex_lock(context, &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; + + err = krb5int_random_string (context, uniquename, sizeof (uniquename)); + if (err) { + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + free(lid); + return err; + } + + 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_cc_mutex_unlock(context, &krb5int_mcc_mutex); + if (err) { + free(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. */ + +krb5_error_code +krb5int_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 ENOMEM; + err = krb5_copy_creds(ctx, creds, &new_node->creds); + if (err) { + free(new_node); + return err; + } + err = k5_cc_mutex_lock(ctx, &mptr->lock); + if (err) + return err; + new_node->next = mptr->link; + mptr->link = new_node; + update_mcc_change_time(mptr); + k5_cc_mutex_unlock(ctx, &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_cc_mutex_lock(context, &krb5int_mcc_mutex); + if (ret) + goto errout; + cdata->cur = mcc_head; + ret = k5_cc_mutex_unlock(context, &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_cc_mutex_lock(context, &krb5int_mcc_mutex); + if (ret) + goto errout; + cdata->cur = cdata->cur->next; + ret = k5_cc_mutex_unlock(context, &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; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_last_change_time( + krb5_context context, + krb5_ccache id, + krb5_timestamp *change_time) +{ + krb5_error_code ret = 0; + krb5_mcc_data *data = (krb5_mcc_data *) id->data; + + *change_time = 0; + + ret = k5_cc_mutex_lock(context, &data->lock); + if (!ret) { + *change_time = data->changetime; + k5_cc_mutex_unlock(context, &data->lock); + } + + return ret; +} + +/* + Utility routine: called by krb5_mcc_* functions to keep + result of krb5_mcc_last_change_time up to date + */ + +static void +update_mcc_change_time(krb5_mcc_data *d) +{ + krb5_timestamp now_time = time(NULL); + d->changetime = (d->changetime >= now_time) ? + d->changetime + 1 : now_time; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_lock(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_mcc_data *data = (krb5_mcc_data *) id->data; + ret = k5_cc_mutex_lock(context, &data->lock); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_unlock(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + krb5_mcc_data *data = (krb5_mcc_data *) id->data; + ret = k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +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, /* move */ + krb5_mcc_last_change_time, + NULL, /* wasdefault */ + krb5_mcc_lock, + krb5_mcc_unlock, +}; diff --git a/krb5-1-7/src/lib/krb5/ccache/cc_mslsa.c b/krb5-1-7/src/lib/krb5/ccache/cc_mslsa.c new file mode 100644 index 000000000..db74828f3 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include +#include + +#define SECURITY_WIN32 +#include +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 +#include +#include + + +/* 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;iNameCount;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; iLength; 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)); + free(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) { + free(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) { + free(lid->data); + free(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()) { + free(data->cc_name); + free(lid->data); + free(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); + free(data); + } + free(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; iCountOfTickets; 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-7/src/lib/krb5/ccache/cc_retr.c b/krb5-1-7/src/lib/krb5/ccache/cc_retr.c new file mode 100644 index 000000000..1e25a048c --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cc_retr.c @@ -0,0 +1,382 @@ +/* + * lib/krb5/ccache/cc_retr.c + * + * Copyright 1990,1991,1999,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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)) + +static int +times_match_exact(const krb5_ticket_times *t1, const krb5_ticket_times *t2) +{ + return (t1->authtime == t2->authtime && + t1->starttime == t2->starttime && + t1->endtime == t2->endtime && + t1->renew_till == t2->renew_till); +} + +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; + + return data_eq(*data1, *data2) ? TRUE : FALSE; +} + +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 = data_eq(in_creds->ticket, in_compare_creds->ticket); + } + + if (equal) { + equal = data_eq(in_creds->second_ticket, in_compare_creds->second_ticket); + } + + 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_eq(*authdata[i], *compare_authdata[i]); + } + if (equal) { equal = (!authdata[i] && !compare_authdata[i]); } + } else { + if (equal) { equal = (!authdata && !compare_authdata); } + } + } + + return equal; +} diff --git a/krb5-1-7/src/lib/krb5/ccache/ccapi/Makefile.in b/krb5-1-7/src/lib/krb5/ccache/ccapi/Makefile.in new file mode 100644 index 000000000..201555a55 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/ccache/ccapi/stdcc.c b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.c new file mode 100644 index 000000000..14569fb59 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.c @@ -0,0 +1,1699 @@ +/* + * 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, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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(_WIN32) || defined(USE_CCAPI) + +#include "k5-int.h" +#include "stdcc.h" +#include "stdcc_util.h" +#include "string.h" +#include + +#if defined(_WIN32) +#include "winccld.h" +#endif + +#ifndef CC_API_VER2 +#define CC_API_VER2 +#endif + +#ifdef DEBUG +#if defined(_WIN32) +#include +#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, /* move */ + krb5_stdccv3_last_change_time, /* lastchange */ + NULL, /* wasdefault */ + krb5_stdccv3_lock, + krb5_stdccv3_unlock, +#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 = strdup (ccstring->data); + if (!name) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + 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 = strdup (residual); + 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) { + 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 (iterator) { + err = cc_credentials_iterator_release(iterator); + } + + 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; + + 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 = strdup (ccstring->data); + if (!name) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + 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; +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_last_change_time + (krb5_context context, krb5_ccache id, + krb5_timestamp *change_time) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_time_t ccapi_change_time = 0; + + *change_time = 0; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + if (!err) { + err = cc_ccache_get_change_time (ccapi_data->NamedCache, &ccapi_change_time); + } + if (!err) { + *change_time = ccapi_change_time; + } + + return cc_err_xlate (err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock +(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) { + err = cc_ccache_lock(ccapi_data->NamedCache, cc_lock_write, cc_lock_block); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock +(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) { + err = cc_ccache_unlock(ccapi_data->NamedCache); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock +(krb5_context context) +{ + krb5_error_code err = 0; + + if (!err && !gCntrlBlock) { + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); + } + if (!err) { + err = cc_context_lock(gCntrlBlock, cc_lock_write, cc_lock_block); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock +(krb5_context context) +{ + krb5_error_code err = 0; + + if (!err && !gCntrlBlock) { + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); + } + if (!err) { + err = cc_context_unlock(gCntrlBlock); + } + return cc_err_xlate(err); +} + +#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); + snprintf(name, 256, "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 = strdup(residual))) + goto errout; + + newCache->ops = &krb5_cc_stdcc_ops; + newCache->data = ccapi_data; + ccapi_data->cache_name = cName; + + 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 */ + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ + diff --git a/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.h b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.h new file mode 100644 index 000000000..e9ec085eb --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc.h @@ -0,0 +1,176 @@ +#ifndef __KRB5_STDCC_H__ +#define __KRB5_STDCC_H__ + +#if defined(_WIN32) || defined(USE_CCAPI) + +#include "k5-int.h" /* loads krb5.h */ + +#ifdef USE_CCAPI_V3 +#include +#else +#if defined(_WIN32) +#include "cacheapi.h" +#else +#include +#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); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_last_change_time + (krb5_context context, krb5_ccache id, + krb5_timestamp *change_time); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock + (krb5_context, krb5_ccache id); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock + (krb5_context, krb5_ccache id); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock + (krb5_context context); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock + (krb5_context context); + +#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 + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ + +#endif diff --git a/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.c b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.c new file mode 100644 index 000000000..a9d1f43d0 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.c @@ -0,0 +1,1068 @@ +/* + * stdcc_util.c + * utility functions used in implementing the ccache api for krb5 + * not publicly exported + * Frank Dabek, July 1998 + */ + +#if defined(_WIN32) || defined(USE_CCAPI) + +#include +#include +#include + +#if defined(_WIN32) +#include +#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; +} + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ diff --git a/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.h b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.h new file mode 100644 index 000000000..2b724eb78 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccapi/stdcc_util.h @@ -0,0 +1,48 @@ +/* stdcc_util.h + * + * Frank Dabek, July 1998 + */ + +#if defined(_WIN32) || defined(USE_CCAPI) + +#include "autoconf.h" + +#if USE_CCAPI_V3 +#include +#else +#if defined(_WIN32) +#include "cacheapi.h" +#else +#include +#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 + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ diff --git a/krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.c b/krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.c new file mode 100644 index 000000000..22646e1ee --- /dev/null +++ b/krb5-1-7/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 +#include +#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-7/src/lib/krb5/ccache/ccapi/winccld.h b/krb5-1-7/src/lib/krb5/ccache/ccapi/winccld.h new file mode 100644 index 000000000..245ae245e --- /dev/null +++ b/krb5-1-7/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 +#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-7/src/lib/krb5/ccache/ccbase.c b/krb5-1-7/src/lib/krb5/ccache/ccbase.c new file mode 100644 index 000000000..f54486f7d --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccbase.c @@ -0,0 +1,619 @@ +/* + * lib/krb5/ccache/ccbase.c + * + * Copyright 1990,2004,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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; + +#define NEXT NULL + +#ifdef _WIN32 +extern const krb5_cc_ops krb5_lcc_ops; +static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_lcc_entry +#endif + +#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, NEXT }; +#undef NEXT +#define NEXT &cc_stdcc_entry +#endif + +static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_mcc_entry + +#ifndef NO_FILE_CCACHE +static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, NEXT }; +#undef NEXT +#define NEXT &cc_fcc_entry +#endif + +#ifdef USE_KEYRING_CCACHE +extern const krb5_cc_ops krb5_krcc_ops; +static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_krcc_entry +#endif /* USE_KEYRING_CCACHE */ + + +#define INITIAL_TYPEHEAD (NEXT) +static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD; +static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +/* mutex for krb5_cccol_[un]lock */ +static k5_cc_mutex cccol_lock = K5_CC_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_cc_mutex_finish_init(&cccol_lock); + if (err) + return err; + err = k5_cc_mutex_finish_init(&krb5int_mcc_mutex); + if (err) + return err; + err = k5_mutex_finish_init(&cc_typelist_lock); + if (err) + return err; +#ifndef NO_FILE_CCACHE + err = k5_cc_mutex_finish_init(&krb5int_cc_file_mutex); + if (err) + return err; +#endif +#ifdef USE_KEYRING_CCACHE + err = k5_cc_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_cccol_force_unlock(); + k5_cc_mutex_destroy(&cccol_lock); + k5_mutex_destroy(&cc_typelist_lock); +#ifndef NO_FILE_CCACHE + k5_cc_mutex_destroy(&krb5int_cc_file_mutex); +#endif + k5_cc_mutex_destroy(&krb5int_mcc_mutex); +#ifdef USE_KEYRING_CCACHE + k5_cc_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, const 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 +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; + + if (name == NULL) + return KRB5_CC_BADNAME; + 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; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_move (krb5_context context, krb5_ccache src, krb5_ccache dst) +{ + krb5_error_code ret = 0; + krb5_principal princ = NULL; + + ret = krb5_cccol_lock(context); + if (ret) { + return ret; + } + + ret = krb5_cc_lock(context, src); + if (ret) { + krb5_cccol_unlock(context); + return ret; + } + + ret = krb5_cc_get_principal(context, src, &princ); + if (!ret) { + ret = krb5_cc_initialize(context, dst, princ); + } + if (!ret) { + ret = krb5_cc_lock(context, dst); + } + if (!ret) { + ret = krb5_cc_copy_creds(context, src, dst); + krb5_cc_unlock(context, dst); + } + + krb5_cc_unlock(context, src); + if (!ret) { + ret = krb5_cc_destroy(context, src); + } + krb5_cccol_unlock(context); + if (princ) { + krb5_free_principal(context, princ); + princ = NULL; + } + + return ret; +} + +krb5_error_code +k5_cc_mutex_init(k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + ret = k5_mutex_init(&m->lock); + if (ret) return ret; + m->owner = NULL; + m->refcount = 0; + + return ret; +} + +krb5_error_code +k5_cc_mutex_finish_init(k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + ret = k5_mutex_finish_init(&m->lock); + if (ret) return ret; + m->owner = NULL; + m->refcount = 0; + + return ret; +} + +void +k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m) +{ +#ifdef DEBUG_THREADS + assert(m->refcount > 0); + assert(m->owner == context); +#endif + k5_assert_locked(&m->lock); +} + +void +k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m) +{ +#ifdef DEBUG_THREADS + assert(m->refcount == 0); + assert(m->owner == NULL); +#endif + k5_assert_unlocked(&m->lock); +} + +krb5_error_code +k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + // not locked or already locked by another context + if (m->owner != context) { + // acquire lock, blocking until available + ret = k5_mutex_lock(&m->lock); + m->owner = context; + m->refcount = 1; + } + // already locked by this context, just increase refcount + else { + m->refcount++; + } + return ret; +} + +krb5_error_code +k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + /* verify owner and sanity check refcount */ + if ((m->owner != context) || (m->refcount < 1)) { + return ret; + } + /* decrement & unlock when count reaches zero */ + m->refcount--; + if (m->refcount == 0) { + m->owner = NULL; + k5_mutex_unlock(&m->lock); + } + return ret; +} + +/* necessary to make reentrant locks play nice with krb5int_cc_finalize */ +krb5_error_code +k5_cc_mutex_force_unlock(k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + m->refcount = 0; + m->owner = NULL; + if (m->refcount > 0) { + k5_mutex_unlock(&m->lock); + } + return ret; +} + +/* + * holds on to all pertype global locks as well as typelist lock + */ + +krb5_error_code KRB5_CALLCONV +krb5_cccol_lock(krb5_context context) +{ + krb5_error_code ret = 0; + + ret = k5_cc_mutex_lock(context, &cccol_lock); + if (ret) { + return ret; + } + ret = k5_mutex_lock(&cc_typelist_lock); + if (ret) { + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } + ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); + if (ret) { + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } + ret = k5_cc_mutex_lock(context, &krb5int_mcc_mutex); + if (ret) { + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } +#ifdef USE_CCAPI_V3 + ret = krb5_stdccv3_context_lock(context); +#endif +#ifdef USE_KEYRING_CCACHE + ret = k5_cc_mutex_lock(context, &krb5int_krcc_mutex); +#endif + if (ret) { + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } + k5_mutex_unlock(&cc_typelist_lock); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cccol_unlock(krb5_context context) +{ + krb5_error_code ret = 0; + + /* sanity check */ + k5_cc_mutex_assert_locked(context, &cccol_lock); + + ret = k5_mutex_lock(&cc_typelist_lock); + if (ret) { + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } + + // unlock each type in the opposite order +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_assert_locked(context, &krb5int_krcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_krcc_mutex); +#endif +#ifdef USE_CCAPI_V3 + krb5_stdccv3_context_unlock(context); +#endif + k5_cc_mutex_assert_locked(context, &krb5int_mcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + k5_cc_mutex_assert_locked(context, &krb5int_cc_file_mutex); + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_mutex_assert_locked(&cc_typelist_lock); + + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + + return ret; +} + +/* necessary to make reentrant locks play nice with krb5int_cc_finalize */ +krb5_error_code +k5_cccol_force_unlock() +{ + krb5_error_code ret = 0; + + /* sanity check */ + if ((&cccol_lock)->refcount == 0) { + return 0; + } + + ret = k5_mutex_lock(&cc_typelist_lock); + if (ret) { + (&cccol_lock)->refcount = 0; + (&cccol_lock)->owner = NULL; + k5_mutex_unlock(&(&cccol_lock)->lock); + return ret; + } + + // unlock each type in the opposite order +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_force_unlock(&krb5int_krcc_mutex); +#endif +#ifdef USE_CCAPI_V3 + krb5_stdccv3_context_unlock(NULL); +#endif + k5_cc_mutex_force_unlock(&krb5int_mcc_mutex); + k5_cc_mutex_force_unlock(&krb5int_cc_file_mutex); + + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_force_unlock(&cccol_lock); + + return ret; +} diff --git a/krb5-1-7/src/lib/krb5/ccache/cccopy.c b/krb5-1-7/src/lib/krb5/ccache/cccopy.c new file mode 100644 index 000000000..a9a45b501 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/ccache/cccursor.c b/krb5-1-7/src/lib/krb5/ccache/cccursor.c new file mode 100644 index 000000000..5a062d443 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/cccursor.c @@ -0,0 +1,366 @@ +/* + * lib/krb5/ccache/cccursor.c + * + * Copyright 2006, 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. + * + * cursor for sequential traversal of ccaches + */ + +#include "cc-int.h" + +#include + +#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; +} + +krb5_error_code KRB5_CALLCONV +krb5_cccol_last_change_time( + krb5_context context, + krb5_timestamp *change_time) +{ + krb5_error_code ret = 0; + krb5_cccol_cursor c = NULL; + krb5_ccache ccache = NULL; + krb5_timestamp last_time = 0; + krb5_timestamp max_change_time = 0; + + *change_time = 0; + + ret = krb5_cccol_cursor_new(context, &c); + + while (!ret) { + ret = krb5_cccol_cursor_next(context, c, &ccache); + if (ccache) { + ret = krb5_cc_last_change_time(context, ccache, &last_time); + if (!ret && last_time > max_change_time) { + max_change_time = last_time; + } + ret = 0; + } + else { + break; + } + } + *change_time = max_change_time; + return ret; +} + +/* + * krb5_cccol_lock and krb5_cccol_unlock are defined in ccbase.c + */ + +/* + * 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-7/src/lib/krb5/ccache/ccdefault.c b/krb5-1-7/src/lib/krb5/ccache/ccdefault.c new file mode 100644 index 000000000..c4f9f292e --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccdefault.c @@ -0,0 +1,144 @@ +/* + * lib/krb5/ccache/ccdefault.c + * + * Copyright 1990, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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_KIM) +#include +#include "kim_library_private.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) +{ + const char *default_name; + + if (!context || context->magic != KV5M_CONTEXT) + return KV5M_CONTEXT; + + default_name = krb5_cc_default_name(context); + if (default_name == NULL) { + /* Could be a bogus context, or an allocation failure, or + other things. Unfortunately the API doesn't allow us + to find out any specifics. */ + return KRB5_FCC_INTERNAL; + } + + return krb5_cc_resolve(context, default_name, 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_KIM + if (kim_library_allow_automatic_prompting ()) { + kim_error err = KIM_NO_ERROR; + kim_ccache kimccache = NULL; + kim_identity identity = KIM_IDENTITY_ANY; + kim_credential_state state; + kim_string name = NULL; + + err = kim_ccache_create_from_display_name (&kimccache, + krb5_cc_default_name (context)); + + if (!err) { + err = kim_ccache_get_client_identity (kimccache, &identity); + } + + if (!err) { + err = kim_ccache_get_state (kimccache, &state); + } + + if (err || state != kim_credentials_state_valid) { + /* Either the ccache is does not exist or is invalid. Get new + * tickets. Use the identity in the ccache if there was one. */ + kim_ccache_free (&kimccache); + err = kim_ccache_create_new (&kimccache, + identity, KIM_OPTIONS_DEFAULT); + } + + if (!err) { + err = kim_ccache_get_display_name (kimccache, &name); + } + + if (!err) { + krb5_cc_set_default_name (context, name); + } + + kim_identity_free (&identity); + kim_string_free (&name); + kim_ccache_free (&kimccache); + } +#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]) { + char * ccdefname = krb5_cc_default_name (context); + if (!ccdefname || strcmp (ccdefname, ccname) != 0) { + krb5_cc_set_default_name (context, ccname); + } + } + } +#endif +#endif + + return krb5_cc_default (context, ccache); +} diff --git a/krb5-1-7/src/lib/krb5/ccache/ccdefops.c b/krb5-1-7/src/lib/krb5/ccache/ccdefops.c new file mode 100644 index 000000000..949758bdf --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccdefops.c @@ -0,0 +1,59 @@ +/* + * 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; + +#elif defined(NO_FILE_CCACHE) + +/* Note that this version isn't likely to work very well for multiple + processes. It's mostly a placeholder so we can experiment with + building the NO_FILE_CCACHE code on UNIX. */ + +extern const krb5_cc_ops krb5_mcc_ops; +const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_mcc_ops; + +#else + +#include "fcc.h" +const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_file_ops; + +#endif diff --git a/krb5-1-7/src/lib/krb5/ccache/ccfns.c b/krb5-1-7/src/lib/krb5/ccache/ccfns.c new file mode 100644 index 000000000..5d95a6428 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/ccfns.c @@ -0,0 +1,193 @@ +/* + * lib/krb5/ccache/ccfns.c + * + * Copyright 2000, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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; + + /* remove any dups */ + krb5_cc_remove_cred(context, cache, 0, creds); + + 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; + /* remove any dups */ + krb5_cc_remove_cred(context, cache, 0, creds); + 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; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_last_change_time (krb5_context context, krb5_ccache ccache, + krb5_timestamp *change_time) +{ + return ccache->ops->lastchange(context, ccache, change_time); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_lock (krb5_context context, krb5_ccache ccache) +{ + return ccache->ops->lock(context, ccache); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_unlock (krb5_context context, krb5_ccache ccache) +{ + return ccache->ops->unlock(context, ccache); +} + diff --git a/krb5-1-7/src/lib/krb5/ccache/deps b/krb5-1-7/src/lib/krb5/ccache/deps new file mode 100644 index 000000000..fa42f24d2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/deps @@ -0,0 +1,126 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 +t_cc.so t_cc.po $(OUTPRE)t_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_cc.c +t_cccursor.so t_cccursor.po $(OUTPRE)t_cccursor.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h t_cccursor.c diff --git a/krb5-1-7/src/lib/krb5/ccache/fcc.h b/krb5-1-7/src/lib/krb5/ccache/fcc.h new file mode 100644 index 000000000..f349da998 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/ccache/scc.h b/krb5-1-7/src/lib/krb5/ccache/scc.h new file mode 100644 index 000000000..98acbc25c --- /dev/null +++ b/krb5-1-7/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 + +#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-7/src/lib/krb5/ccache/ser_cc.c b/krb5-1-7/src/lib/krb5/ccache/ser_cc.c new file mode 100644 index 000000000..d2abf532d --- /dev/null +++ b/krb5-1-7/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: + * : + */ + 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 (ccache->ops && ccache->ops->prefix) { + if (asprintf(&ccname, "%s:%s", ccache->ops->prefix, fnamep) < 0) + ccname = NULL; + } else + ccname = strdup(fnamep); + + if (ccname) { + /* 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-7/src/lib/krb5/ccache/t_cc.c b/krb5-1-7/src/lib/krb5/ccache/t_cc.c new file mode 100644 index 000000000..f941bb60f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/ccache/t_cc.c @@ -0,0 +1,412 @@ +/* + * 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 "k5-int.h" +#include +#include +#include "autoconf.h" +#ifdef HAVE_UNISTD_H +#include +#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 krb5_error_code init_test_cred(krb5_context context) +{ + krb5_error_code kret; + unsigned int i; + krb5_authdata *a; +#define REALM "REALM" + kret = krb5_build_principal(context, &test_creds.client, sizeof(REALM), REALM, + "client-comp1", "client-comp2", NULL); + if(kret) + return kret; + + kret = krb5_build_principal(context, &test_creds.server, sizeof(REALM), REALM, + "server-comp1", "server-comp2", NULL); + if(kret) { + krb5_free_principal(context, test_creds.client); + test_creds.client = 0; + goto cleanup; + } + + test_creds.authdata = malloc (3 * sizeof(krb5_authdata *)); + if (!test_creds.authdata) { + kret = ENOMEM; + goto cleanup; + } + + for (i = 0 ; i <= 2 ; i++) { + test_creds.authdata[i] = 0; + } + a = (krb5_authdata *) malloc(sizeof(krb5_authdata)); + if(!a) { + kret = ENOMEM; + goto cleanup; + } + a->magic = KV5M_AUTHDATA; + a->ad_type = KRB5_AUTHDATA_IF_RELEVANT; + a->contents = (krb5_octet * ) malloc(1); + if(!a->contents) { + free(a); + kret = ENOMEM; + goto cleanup; + } + a->contents[0]=5; + a->length = 1; + test_creds.authdata[0] = a; + + a = (krb5_authdata *) malloc(sizeof(krb5_authdata)); + if(!a) { + kret = ENOMEM; + goto cleanup; + } + a->magic = KV5M_AUTHDATA; + a->ad_type = KRB5_AUTHDATA_KDC_ISSUED; + a->contents = (krb5_octet * ) malloc(2); + if(!a->contents) { + free(a); + kret = ENOMEM; + goto cleanup; + } + a->contents[0]=4; + a->contents[1]=6; + a->length = 2; + test_creds.authdata[1] = a; + +cleanup: + if(kret) { + if (test_creds.client) { + krb5_free_principal(context, test_creds.client); + test_creds.client = 0; + } + if (test_creds.server) { + krb5_free_principal(context, test_creds.server); + test_creds.server = 0; + + } + if (test_creds.authdata) { + krb5_free_authdata(context, test_creds.authdata); + test_creds.authdata = 0; + } + } + + return kret; +} + +static void free_test_cred(krb5_context context) +{ + krb5_free_principal(context, test_creds.client); + + krb5_free_principal(context, test_creds.server); + + if(test_creds.authdata) { + krb5_free_authdata(context, test_creds.authdata); + test_creds.authdata = 0; + } +} + +#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; + + kret = init_test_cred(context); + CHECK(kret, "init_creds"); + + 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*/ + snprintf(newcache, sizeof(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; + + snprintf(name, sizeof(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]; + + snprintf(name, sizeof(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; + const 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; + + 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-7/src/lib/krb5/ccache/t_cccursor.c b/krb5-1-7/src/lib/krb5/ccache/t_cccursor.c new file mode 100644 index 000000000..e65beadd0 --- /dev/null +++ b/krb5-1-7/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 +#include +#include +#include + +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-7/src/lib/krb5/ccache/t_memory.c b/krb5-1-7/src/lib/krb5/ccache/t_memory.c new file mode 100644 index 000000000..b117aed33 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/ccache/t_stdio.c b/krb5-1-7/src/lib/krb5/ccache/t_stdio.c new file mode 100644 index 000000000..a76d1fcd7 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/deps b/krb5-1-7/src/lib/krb5/deps new file mode 100644 index 000000000..1923dd2cf --- /dev/null +++ b/krb5-1-7/src/lib/krb5/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +krb5_libinit.so krb5_libinit.po $(OUTPRE)krb5_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-7/src/lib/krb5/error_tables/Makefile.in b/krb5-1-7/src/lib/krb5/error_tables/Makefile.in new file mode 100644 index 000000000..ec4c9202c --- /dev/null +++ b/krb5-1-7/src/lib/krb5/error_tables/Makefile.in @@ -0,0 +1,60 @@ +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) + +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@ + diff --git a/krb5-1-7/src/lib/krb5/error_tables/asn1_err.et b/krb5-1-7/src/lib/krb5/error_tables/asn1_err.et new file mode 100644 index 000000000..06078ffbc --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/error_tables/deps b/krb5-1-7/src/lib/krb5/error_tables/deps new file mode 100644 index 000000000..3828bd380 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/error_tables/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +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-7/src/lib/krb5/error_tables/init_ets.c b/krb5-1-7/src/lib/krb5/error_tables/init_ets.c new file mode 100644 index 000000000..56a750e75 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/error_tables/kdb5_err.et b/krb5-1-7/src/lib/krb5/error_tables/kdb5_err.et new file mode 100644 index 000000000..cd7214d9b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/error_tables/kdb5_err.et @@ -0,0 +1,86 @@ +# +# lib/krb5/error_tables/kdb5_err.et +# +# Copyright 1990, 2008 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.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_NOACTMASTERKEY, "Cannot find active master key" +ec KRB5_KDB_KVNONOMATCH, "KVNO of new master key does not match expected value" +ec KRB5_KDB_STORED_MKEY_NOTCURRENT, "Stored master key is not current" + +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" +ec KRB5_LOG_CONV, "Update log conversion error" +ec KRB5_LOG_UNSTABLE, "Update log is unstable" +ec KRB5_LOG_CORRUPT, "Update log is corrupt" +ec KRB5_LOG_ERROR, "Generic update log error" + +end diff --git a/krb5-1-7/src/lib/krb5/error_tables/krb524_err.et b/krb5-1-7/src/lib/krb5/error_tables/krb524_err.et new file mode 100644 index 000000000..5a4a004c7 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/error_tables/krb5_err.et b/krb5-1-7/src/lib/krb5/error_tables/krb5_err.et new file mode 100644 index 000000000..c7c91dff9 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/error_tables/krb5_err.et @@ -0,0 +1,354 @@ +# +# 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 KRB5KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only" +error_code KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KDC policy rejects transited path" +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 KRB5KRB_AP_ERR_NO_TGT, "No ticket granting ticket" +error_code KRB5KDC_ERR_WRONG_REALM, "Realm not local to KDC" +error_code KRB5KRB_AP_ERR_USER_TO_USER_REQUIRED, "User to user required" +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 KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION, "An unsupported critical FAST option was requested" +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" + +error_code KRB5_ERR_INVALID_UTF8, "Invalid UTF-8 string" +error_code KRB5_ERR_FAST_REQUIRED, "FAST protected pre-authentication required but not supported by KDC" + +error_code KRB5_LOCAL_ADDR_REQUIRED, "Auth context must contain local address" +error_code KRB5_REMOTE_ADDR_REQUIRED, "Auth context must contain remote address" +end diff --git a/krb5-1-7/src/lib/krb5/error_tables/kv5m_err.et b/krb5-1-7/src/lib/krb5/error_tables/kv5m_err.et new file mode 100644 index 000000000..d68398cf9 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/error_tables/kv5m_err.et @@ -0,0 +1,92 @@ +# +# 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" +error_code KV5M_FAST_ARMORED_REQ, "Bad magic number for fast armored request" +error_code KV5M_FAST_REQ, "Bad magic number for FAST request" +error_code KV5M_FAST_RESPONSE, "Bad magic number for FAST response" +end diff --git a/krb5-1-7/src/lib/krb5/keytab/Makefile.in b/krb5-1-7/src/lib/krb5/keytab/Makefile.in new file mode 100644 index 000000000..c422e9c93 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/Makefile.in @@ -0,0 +1,80 @@ +thisconfigdir=../../.. +myfulldir=lib/krb5/keytab +mydir=lib/krb5/keytab +BUILDTOP=$(REL)..$(S)..$(S).. +DEFS= + +RUN_SETUP = @KRB5_RUN_ENV@ +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +##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_memory.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_memory.$(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_memory.c \ + $(srcdir)/kt_srvtab.c \ + $(srcdir)/read_servi.c + +EXTRADEPSRCS= \ + $(srcdir)/t_keytab.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 + +check-unix:: t_keytab + KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) ./t_keytab + +T_KEYTAB_OBJS = t_keytab.o +t_keytab: $(T_KEYTAB_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_KEYTAB_OBJS) $(KRB5_BASE_LIBS) + +clean-unix:: + $(RM) t_keytab t_keytab.o + +clean-windows:: + @echo Making clean in krb5\keytab + $(RM) $(OBJFILE) + + +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/krb5/keytab/deps b/krb5-1-7/src/lib/krb5/keytab/deps new file mode 100644 index 000000000..32ab2bc41 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/deps @@ -0,0 +1,113 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_memory.so kt_memory.po $(OUTPRE)kt_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 kt_memory.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +t_keytab.so t_keytab.po $(OUTPRE)t_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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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_keytab.c diff --git a/krb5-1-7/src/lib/krb5/keytab/kt-int.h b/krb5-1-7/src/lib/krb5/keytab/kt-int.h new file mode 100644 index 000000000..e62b2d3f1 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/kt-int.h @@ -0,0 +1,42 @@ +/* + * 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); + +int krb5int_mkt_initialize(void); + +void krb5int_mkt_finalize(void); +#endif /* __KRB5_KEYTAB_INT_H__ */ diff --git a/krb5-1-7/src/lib/krb5/keytab/kt_file.c b/krb5-1-7/src/lib/krb5/keytab/kt_file.c new file mode 100644 index 000000000..90f6bd8c8 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/kt_file.c @@ -0,0 +1,1765 @@ +/* + * lib/krb5/keytab/kt_file.c + * + * Copyright 1990,1991,1995,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 LEAN_CLIENT + +#include "k5-int.h" +#include + +/* + * Information needed by internal routines of the file-based ticket + * cache implementation. + */ + + +/* + * Constants + */ + +#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 */ + unsigned int iter_count; /* Number of active iterators */ + long start_offset; /* Starting offset after version */ + k5_mutex_t lock; /* Protect openf, version */ +} krb5_ktfile_data; + +/* + * Some limitations: + * + * If the file OPENF is left open between calls, we have an iterator + * active, and OPENF is opened in read-only mode. So, no changes + * can be made via that handle. + * + * An advisory file lock is used while the file is open. Thus, + * multiple handles on the same underlying file cannot be used without + * disrupting the locking in effect. + * + * The start_offset field is only valid if the file is open. It will + * almost certainly always be the same constant. It's used so that + * if an iterator is active, and we start another one, we don't have + * to seek back to the start and re-read the version number to set + * the position for the iterator. + */ + +/* + * 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 KTITERS(id) (((krb5_ktfile_data *)(id)->data)->iter_count) +#define KTSTARTOFF(id) (((krb5_ktfile_data *)(id)->data)->start_offset) +#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; + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_resolve + (krb5_context, + const char *, + krb5_keytab *); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_wresolve + (krb5_context, + const char *, + krb5_keytab *); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_get_name + (krb5_context, + krb5_keytab, + char *, + unsigned int); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_close + (krb5_context, + krb5_keytab); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_get_entry + (krb5_context, + krb5_keytab, + krb5_const_principal, + krb5_kvno, + krb5_enctype, + krb5_keytab_entry *); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_start_seq_get + (krb5_context, + krb5_keytab, + krb5_kt_cursor *); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_get_next + (krb5_context, + krb5_keytab, + krb5_keytab_entry *, + krb5_kt_cursor *); + +static 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) */ +static krb5_error_code KRB5_CALLCONV krb5_ktfile_add + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +static krb5_error_code KRB5_CALLCONV krb5_ktfile_remove + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +static krb5_error_code krb5_ktfileint_openr + (krb5_context, + krb5_keytab); + +static krb5_error_code krb5_ktfileint_openw + (krb5_context, + krb5_keytab); + +static krb5_error_code krb5_ktfileint_close + (krb5_context, + krb5_keytab); + +static krb5_error_code krb5_ktfileint_read_entry + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +static krb5_error_code krb5_ktfileint_write_entry + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +static krb5_error_code krb5_ktfileint_delete_entry + (krb5_context, + krb5_keytab, + krb5_int32); + +static krb5_error_code krb5_ktfileint_internal_read_entry + (krb5_context, + krb5_keytab, + krb5_keytab_entry *, + krb5_int32 *); + +static krb5_error_code krb5_ktfileint_size_entry + (krb5_context, + krb5_keytab_entry *, + krb5_int32 *); + +static 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. + */ + +static krb5_error_code +ktfile_common_resolve(krb5_context context, const char *name, + krb5_keytab *id, const struct _krb5_kt_ops *ops) +{ + krb5_ktfile_data *data; + krb5_error_code err; + + if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL) + return(ENOMEM); + + (*id)->ops = ops; + if ((data = (krb5_ktfile_data *)malloc(sizeof(krb5_ktfile_data))) == NULL) { + free(*id); + return(ENOMEM); + } + + err = k5_mutex_init(&data->lock); + if (err) { + free(data); + free(*id); + return err; + } + + if ((data->name = strdup(name)) == NULL) { + k5_mutex_destroy(&data->lock); + free(data); + free(*id); + return(ENOMEM); + } + + data->openf = 0; + data->version = 0; + data->iter_count = 0; + + (*id)->data = (krb5_pointer)data; + (*id)->magic = KV5M_KEYTAB; + return(0); +} + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_resolve(krb5_context context, const char *name, krb5_keytab *id) +{ + return ktfile_common_resolve(context, name, id, &krb5_ktf_writable_ops); +} + + +/* + * "Close" a file-based keytab and invalidate the id. This means + * free memory hidden in the structures. + */ + +static 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(). + */ +{ + free(KTFILENAME(id)); + zap(KTFILEBUFP(id), BUFSIZ); + k5_mutex_destroy(&((krb5_ktfile_data *)id->data)->lock); + free(id->data); + id->ops = 0; + free(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. + */ + +static 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; + int was_open; + + kerror = KTLOCK(id); + if (kerror) + return kerror; + + if (KTFILEP(id) != NULL) { + was_open = 1; + + if (fseek(KTFILEP(id), KTSTARTOFF(id), SEEK_SET) == -1) { + KTUNLOCK(id); + return errno; + } + } else { + was_open = 0; + + /* 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) { + if (was_open == 0) + (void) krb5_ktfileint_close(context, id); + KTUNLOCK(id); + krb5_kt_free_entry(context, &cur_entry); + return kerror; + } + if (was_open == 0 && (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. + */ + +static 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. + */ +{ + int result; + + memset(name, 0, len); + result = snprintf(name, len, "%s:%s", id->ops->prefix, KTFILENAME(id)); + if (SNPRINTF_OVERFLOW(result, len)) + return(KRB5_KT_NAME_TOOLONG); + return(0); +} + +/* + * krb5_ktfile_start_seq_get() + */ + +static 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 (KTITERS(id) == 0) { + if ((retval = krb5_ktfileint_openr(context, id))) { + KTUNLOCK(id); + return retval; + } + } + + if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) { + if (KTITERS(id) == 0) + krb5_ktfileint_close(context, id); + KTUNLOCK(id); + return ENOMEM; + } + *fileoff = KTSTARTOFF(id); + *cursorp = (krb5_kt_cursor)fileoff; + KTITERS(id)++; + if (KTITERS(id) == 0) { + /* Wrapped?! */ + KTITERS(id)--; + KTUNLOCK(id); + krb5_set_error_message(context, KRB5_KT_IOERR, + "Too many keytab iterators active"); + return KRB5_KT_IOERR; /* XXX */ + } + KTUNLOCK(id); + + return 0; +} + +/* + * krb5_ktfile_get_next() + */ + +static 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() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) +{ + krb5_error_code kerror; + + free(*cursor); + kerror = KTLOCK(id); + if (kerror) + return kerror; + KTITERS(id)--; + if (KTFILEP(id) != NULL && KTITERS(id) == 0) + kerror = krb5_ktfileint_close(context, id); + else + kerror = 0; + 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: + * : + * 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 (keytab->ops && keytab->ops->prefix) { + if (asprintf(&ktname, "%s:%s", keytab->ops->prefix, fnamep) < 0) + ktname = NULL; + } else + ktname = strdup(fnamep); + + if (ktname) { + /* 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)) + free(KTFILENAME(keytab)); + free(keytab->data); + } + free(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. + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_wresolve(krb5_context context, const char *name, krb5_keytab *id) +{ + return ktfile_common_resolve(context, name, id, &krb5_ktf_writable_ops); +} + + +/* + * krb5_ktfile_add() + */ + +static 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 (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + krb5_set_error_message(context, KRB5_KT_IOERR, + "Cannot change keytab with keytab iterators active"); + return KRB5_KT_IOERR; /* XXX */ + } + 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() + */ + +static 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 (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + krb5_set_error_message(context, KRB5_KT_IOERR, + "Cannot change keytab with keytab iterators active"); + return KRB5_KT_IOERR; /* XXX */ + } + + 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: + * + * + * + * principal timestamp vno key + * + * 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)) + goto report_errno; + writevno = 1; + } else { + report_errno: + switch (errno) { + case 0: + /* XXX */ + return EMFILE; + case ENOENT: + krb5_set_error_message(context, ENOENT, + "Key table file '%s' not found", + KTFILENAME(id)); + return ENOENT; + default: + return errno; + } + } + } + set_cloexec_file(KTFILEP(id)); + 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)); + KTFILEP(id) = 0; + 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)); + KTFILEP(id) = 0; + 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)); + KTFILEP(id) = 0; + return KRB5_KEYTAB_BADVNO; + } + } + KTSTARTOFF(id) = ftell(KTFILEP(id)); + return 0; +} + +static krb5_error_code +krb5_ktfileint_openr(krb5_context context, krb5_keytab id) +{ + return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_SHARED); +} + +static krb5_error_code +krb5_ktfileint_openw(krb5_context context, krb5_keytab id) +{ + return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_EXCLUSIVE); +} + +static 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; +} + +static 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; +} + +static 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; +} + +static 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); +} + +static 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 = -1; + 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. + */ +static 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) + */ +static 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; + } + found = TRUE; + } + } + } + + return 0; +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/kt_memory.c b/krb5-1-7/src/lib/krb5/keytab/kt_memory.c new file mode 100644 index 000000000..1f7717187 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/kt_memory.c @@ -0,0 +1,669 @@ +/* + * lib/krb5/keytab/kt_memory.c + * + * Copyright 2007 by 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. + */ + +#include "k5-int.h" +#include "kt-int.h" +#include + +#ifndef LEAN_CLIENT + +#define HEIMDAL_COMPATIBLE + +/* + * Information needed by internal routines of the file-based ticket + * cache implementation. + */ + + +/* + * Constants + */ + +/* + * Types + */ +/* From krb5.h: + * 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; + */ + +/* Individual key entries within a table, in a linked list */ +typedef struct _krb5_mkt_link { + struct _krb5_mkt_link *next; + krb5_keytab_entry *entry; +} krb5_mkt_link, *krb5_mkt_cursor; + +/* Per-keytab data header */ +typedef struct _krb5_mkt_data { + char *name; /* Name of the keytab */ + k5_mutex_t lock; /* Thread-safety - all but link */ + krb5_int32 refcount; + krb5_mkt_cursor link; +} krb5_mkt_data; + +/* List of memory key tables */ +typedef struct _krb5_mkt_list_node { + struct _krb5_mkt_list_node *next; + krb5_keytab keytab; +} krb5_mkt_list_node; + +/* Iterator over memory key tables */ +typedef struct _krb5_mkt_ptcursor_data { + struct _krb5_mkt_list_node *cur; +} krb5_mkt_ptcursor_data; + +/* + * Globals + */ +static krb5_mkt_list_node * krb5int_mkt_list = NULL; +static k5_mutex_t krb5int_mkt_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +/* + * Macros + */ +#define KTLOCK(id) k5_mutex_lock(&(((krb5_mkt_data *)(id)->data)->lock)) +#define KTUNLOCK(id) k5_mutex_unlock(&(((krb5_mkt_data *)(id)->data)->lock)) +#define KTCHECKLOCK(id) k5_mutex_assert_locked(&(((krb5_mkt_data *)(id)->data)->lock)) + +#define KTGLOCK k5_mutex_lock(&krb5int_mkt_mutex) +#define KTGUNLOCK k5_mutex_unlock(&krb5int_mkt_mutex) +#define KTGCHECKLOCK k5_mutex_assert_locked(&krb5int_mkt_mutex) + +#define KTLINK(id) (((krb5_mkt_data *)(id)->data)->link) +#define KTREFCNT(id) (((krb5_mkt_data *)(id)->data)->refcount) +#define KTNAME(id) (((krb5_mkt_data *)(id)->data)->name) + +extern const struct _krb5_kt_ops krb5_mkt_ops; + +krb5_error_code KRB5_CALLCONV krb5_mkt_resolve + (krb5_context, + const char *, + krb5_keytab *); + +krb5_error_code KRB5_CALLCONV krb5_mkt_get_name + (krb5_context, + krb5_keytab, + char *, + unsigned int); + +krb5_error_code KRB5_CALLCONV krb5_mkt_close + (krb5_context, + krb5_keytab); + +krb5_error_code KRB5_CALLCONV krb5_mkt_get_entry + (krb5_context, + krb5_keytab, + krb5_const_principal, + krb5_kvno, + krb5_enctype, + krb5_keytab_entry *); + +krb5_error_code KRB5_CALLCONV krb5_mkt_start_seq_get + (krb5_context, + krb5_keytab, + krb5_kt_cursor *); + +krb5_error_code KRB5_CALLCONV krb5_mkt_get_next + (krb5_context, + krb5_keytab, + krb5_keytab_entry *, + krb5_kt_cursor *); + +krb5_error_code KRB5_CALLCONV krb5_mkt_end_get + (krb5_context, + krb5_keytab, + krb5_kt_cursor *); + +/* routines to be included on extended version (write routines) */ +krb5_error_code KRB5_CALLCONV krb5_mkt_add + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +krb5_error_code KRB5_CALLCONV krb5_mkt_remove + (krb5_context, + krb5_keytab, + krb5_keytab_entry *); + +int krb5int_mkt_initialize(void) { + return k5_mutex_finish_init(&krb5int_mkt_mutex); +} + +void krb5int_mkt_finalize(void) { + krb5_mkt_list_node *node, *next_node; + krb5_mkt_cursor cursor, next_cursor; + + k5_mutex_destroy(&krb5int_mkt_mutex); + + for (node = krb5int_mkt_list; node; node = next_node) { + next_node = node->next; + + /* destroy the contents of node->keytab */ + free(KTNAME(node->keytab)); + + /* free the keytab entries */ + for (cursor = KTLINK(node->keytab); cursor; cursor = next_cursor) { + next_cursor = cursor->next; + /* the call to krb5_kt_free_entry uses a NULL in place of the + * krb5_context since we know that the context isn't used by + * krb5_kt_free_entry or krb5_free_principal. */ + krb5_kt_free_entry(NULL, cursor->entry); + free(cursor->entry); + free(cursor); + } + + /* destroy the lock */ + k5_mutex_destroy(&(((krb5_mkt_data *)node->keytab->data)->lock)); + + /* free the private data */ + free(node->keytab->data); + + /* and the keytab */ + free(node->keytab); + + /* and finally the node */ + free(node); + } +} +/* + * This is an implementation specific resolver. It returns a keytab + * initialized with memory keytab routines. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_resolve(krb5_context context, const char *name, krb5_keytab *id) +{ + krb5_mkt_data *data = 0; + krb5_mkt_list_node *list; + krb5_error_code err = 0; + + /* First determine if a memory keytab of this name already exists */ + err = KTGLOCK; + if (err) + return(err); + + for (list = krb5int_mkt_list; list; list = list->next) + { + if (strcmp(name,KTNAME(list->keytab)) == 0) { + /* Found */ + *id = list->keytab; + goto done; + } + } + + /* We will now create the new key table with the specified name. + * We do not drop the global lock, therefore the name will indeed + * be unique when we add it. + */ + + if ((list = (krb5_mkt_list_node *)malloc(sizeof(krb5_mkt_list_node))) == NULL) { + err = ENOMEM; + goto done; + } + + if ((list->keytab = (krb5_keytab)malloc(sizeof(struct _krb5_kt))) == NULL) { + free(list); + err = ENOMEM; + goto done; + } + + list->keytab->ops = &krb5_mkt_ops; + if ((data = (krb5_mkt_data *)malloc(sizeof(krb5_mkt_data))) == NULL) { + free(list->keytab); + free(list); + err = ENOMEM; + goto done; + } + data->name = NULL; + + err = k5_mutex_init(&data->lock); + if (err) { + free(data); + free(list->keytab); + free(list); + goto done; + } + + if ((data->name = strdup(name)) == NULL) { + k5_mutex_destroy(&data->lock); + free(data); + free(list->keytab); + free(list); + err = ENOMEM; + goto done; + } + + data->link = NULL; + data->refcount = 0; + list->keytab->data = (krb5_pointer)data; + list->keytab->magic = KV5M_KEYTAB; + + list->next = krb5int_mkt_list; + krb5int_mkt_list = list; + + *id = list->keytab; + + done: + err = KTLOCK(*id); + if (err) { + k5_mutex_destroy(&data->lock); + if (data && data->name) + free(data->name); + free(data); + if (list && list->keytab) + free(list->keytab); + free(list); + } else { + KTREFCNT(*id)++; + KTUNLOCK(*id); + } + + KTGUNLOCK; + return(err); +} + + +/* + * "Close" a memory-based keytab. This is effectively a no-op. + * We check to see if the keytab exists and that is about it. + * Closing a file keytab does not destroy the contents. Closing + * a memory keytab shouldn't either. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_close(krb5_context context, krb5_keytab id) +{ + krb5_mkt_list_node **listp; +#ifdef HEIMDAL_COMPATIBLE + krb5_mkt_list_node *node; + krb5_mkt_data * data; +#endif + krb5_error_code err = 0; + + /* First determine if a memory keytab of this name already exists */ + err = KTGLOCK; + if (err) + return(err); + + for (listp = &krb5int_mkt_list; *listp; listp = &((*listp)->next)) + { + if (id == (*listp)->keytab) { + /* Found */ + break; + } + } + + if (*listp == NULL) { + /* The specified keytab could not be found */ + err = KRB5_KT_NOTFOUND; + goto done; + } + + /* reduce the refcount and return */ + err = KTLOCK(id); + if (err) + goto done; + + KTREFCNT(id)--; + KTUNLOCK(id); + +#ifdef HEIMDAL_COMPATIBLE + /* In Heimdal if the refcount hits 0, the MEMORY keytab is + * destroyed since there is no krb5_kt_destroy function. + * There is no need to lock the entry while performing + * these operations as the refcount will be 0 and we are + * holding the global lock. + */ + data = (krb5_mkt_data *)id->data; + if (data->refcount == 0) { + krb5_mkt_cursor cursor, next_cursor; + + node = *listp; + *listp = node->next; + + /* destroy the contents of node->keytab (aka id) */ + free(data->name); + + /* free the keytab entries */ + for (cursor = KTLINK(node->keytab); cursor; cursor = next_cursor) { + next_cursor = cursor->next; + + krb5_kt_free_entry(context, cursor->entry); + free(cursor->entry); + free(cursor); + } + + /* destroy the lock */ + k5_mutex_destroy(&(data->lock)); + + /* free the private data */ + free(data); + + /* and the keytab */ + free(node->keytab); + + /* and finally the node */ + free(node); + } +#endif /* HEIMDAL_COMPATIBLE */ + + done: + KTGUNLOCK; + return(err); +} + +/* + * This is the get_entry routine for the memory based keytab implementation. + * It either retrieves the entry or returns an error. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_entry(krb5_context context, krb5_keytab id, + krb5_const_principal principal, krb5_kvno kvno, + krb5_enctype enctype, krb5_keytab_entry *out_entry) +{ + krb5_mkt_cursor cursor; + krb5_keytab_entry *entry, *match = NULL; + krb5_error_code err = 0; + int found_wrong_kvno = 0; + krb5_boolean similar = 0; + + err = KTLOCK(id); + if (err) + return err; + + for (cursor = KTLINK(id); cursor && cursor->entry; cursor = cursor->next) { + entry = cursor->entry; + + /* if the principal isn't the one requested, continue to the next. */ + + if (!krb5_principal_compare(context, principal, entry->principal)) + continue; + + /* if the enctype is not ignored and doesn't match, + and continue to the next */ + if (enctype != IGNORE_ENCTYPE) { + if ((err = krb5_c_enctype_compare(context, enctype, + entry->key.enctype, + &similar))) { + /* we can't determine the enctype of the entry */ + continue; + } + + if (!similar) + continue; + } + + if (kvno == IGNORE_VNO) { + if (match == NULL) + match = entry; + else if (entry->vno > match->vno) + match = entry; + } else { + if (entry->vno == kvno) { + match = entry; + break; + } else { + found_wrong_kvno++; + } + } + } + + /* if we found an entry that matches, ... */ + if (match) { + out_entry->magic = match->magic; + out_entry->timestamp = match->timestamp; + out_entry->vno = match->vno; + out_entry->key = match->key; + err = krb5_copy_keyblock_contents(context, &(match->key), + &(out_entry->key)); + /* + * Coerce the enctype of the output keyblock in case we + * got an inexact match on the enctype. + */ + if(enctype != IGNORE_ENCTYPE) + out_entry->key.enctype = enctype; + if(!err) { + err = krb5_copy_principal(context, + match->principal, + &(out_entry->principal)); + } + } else { + if (!err) + err = found_wrong_kvno ? KRB5_KT_KVNONOTFOUND : KRB5_KT_NOTFOUND; + } + + KTUNLOCK(id); + return(err); +} + +/* + * Get the name of the memory-based keytab. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len) +{ + int result; + + memset(name, 0, len); + result = snprintf(name, len, "%s:%s", id->ops->prefix, KTNAME(id)); + if (SNPRINTF_OVERFLOW(result, len)) + return(KRB5_KT_NAME_TOOLONG); + return(0); +} + +/* + * krb5_mkt_start_seq_get() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp) +{ + krb5_error_code err = 0; + + err = KTLOCK(id); + if (err) + return(err); + + *cursorp = (krb5_kt_cursor)KTLINK(id); + KTUNLOCK(id); + + return(0); +} + +/* + * krb5_mkt_get_next() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor) +{ + krb5_mkt_cursor mkt_cursor = (krb5_mkt_cursor)*cursor; + krb5_error_code err = 0; + + err = KTLOCK(id); + if (err) + return err; + + if (mkt_cursor == NULL) { + KTUNLOCK(id); + return KRB5_KT_END; + } + + entry->magic = mkt_cursor->entry->magic; + entry->timestamp = mkt_cursor->entry->timestamp; + entry->vno = mkt_cursor->entry->vno; + entry->key = mkt_cursor->entry->key; + err = krb5_copy_keyblock_contents(context, &(mkt_cursor->entry->key), + &(entry->key)); + if (!err) + err = krb5_copy_principal(context, mkt_cursor->entry->principal, + &(entry->principal)); + if (!err) + *cursor = (krb5_kt_cursor *)mkt_cursor->next; + KTUNLOCK(id); + return(err); +} + +/* + * krb5_mkt_end_get() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) +{ + *cursor = NULL; + return(0); +} + + +/* + * krb5_mkt_add() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_add(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_error_code err = 0; + krb5_mkt_cursor cursor; + + err = KTLOCK(id); + if (err) + return err; + + cursor = (krb5_mkt_cursor)malloc(sizeof(krb5_mkt_link)); + if (cursor == NULL) { + err = ENOMEM; + goto done; + } + cursor->entry = (krb5_keytab_entry *)malloc(sizeof(krb5_keytab_entry)); + if (cursor->entry == NULL) { + free(cursor); + err = ENOMEM; + goto done; + } + cursor->entry->magic = entry->magic; + cursor->entry->timestamp = entry->timestamp; + cursor->entry->vno = entry->vno; + err = krb5_copy_keyblock_contents(context, &(entry->key), + &(cursor->entry->key)); + if (err) { + free(cursor->entry); + free(cursor); + goto done; + } + + err = krb5_copy_principal(context, entry->principal, &(cursor->entry->principal)); + if (err) { + krb5_free_keyblock_contents(context, &(cursor->entry->key)); + free(cursor->entry); + free(cursor); + goto done; + } + + if (KTLINK(id) == NULL) { + cursor->next = NULL; + KTLINK(id) = cursor; + } else { + cursor->next = KTLINK(id); + KTLINK(id) = cursor; + } + + done: + KTUNLOCK(id); + return err; +} + +/* + * krb5_mkt_remove() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_mkt_cursor *pcursor, next; + krb5_error_code err = 0; + + err = KTLOCK(id); + if (err) + return err; + + if ( KTLINK(id) == NULL ) { + err = KRB5_KT_NOTFOUND; + goto done; + } + + for ( pcursor = &KTLINK(id); *pcursor; pcursor = &(*pcursor)->next ) { + if ( (*pcursor)->entry->vno == entry->vno && + (*pcursor)->entry->key.enctype == entry->key.enctype && + krb5_principal_compare(context, (*pcursor)->entry->principal, entry->principal)) + break; + } + + if (!*pcursor) { + err = KRB5_KT_NOTFOUND; + goto done; + } + + krb5_kt_free_entry(context, (*pcursor)->entry); + free((*pcursor)->entry); + next = (*pcursor)->next; + free(*pcursor); + (*pcursor) = next; + + done: + KTUNLOCK(id); + return err; +} + + +/* + * krb5_mkt_ops + */ + +const struct _krb5_kt_ops krb5_mkt_ops = { + 0, + "MEMORY", /* Prefix -- this string should not appear anywhere else! */ + krb5_mkt_resolve, + krb5_mkt_get_name, + krb5_mkt_close, + krb5_mkt_get_entry, + krb5_mkt_start_seq_get, + krb5_mkt_get_next, + krb5_mkt_end_get, + krb5_mkt_add, + krb5_mkt_remove, + NULL +}; + +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/kt_srvtab.c b/krb5-1-7/src/lib/krb5/keytab/kt_srvtab.c new file mode 100644 index 000000000..20ea3d755 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/kt_srvtab.c @@ -0,0 +1,468 @@ +/* + * lib/krb5/keytab/srvtab/kts_resolv.c + * + * Copyright 1990,1991,2002,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#ifndef LEAN_CLIENT + +/* + * Constants + */ + +#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; + + 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) { + free(*id); + return(ENOMEM); + } + + data->name = strdup(name); + if (data->name == NULL) { + free(data); + free(*id); + return(ENOMEM); + } + + 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(). + */ +{ + free(KTFILENAME(id)); + free(id->data); + id->ops = 0; + free(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. + */ +{ + int result; + + memset(name, 0, len); + result = snprintf(name, len, "%s:%s", id->ops->prefix, KTFILENAME(id)); + if (SNPRINTF_OVERFLOW(result, len)) + return(KRB5_KT_NAME_TOOLONG); + 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) +{ + free(*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 + +#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; + set_cloexec_file(KTFILEP(id)); + 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; +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktadd.c b/krb5-1-7/src/lib/krb5/keytab/ktadd.c new file mode 100644 index 000000000..360dd64cd --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktadd.c @@ -0,0 +1,43 @@ +/* + * lib/krb5/keytab/ktadd.c + * + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" + +#ifndef LEAN_CLIENT + +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; +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktbase.c b/krb5-1-7/src/lib/krb5/keytab/ktbase.c new file mode 100644 index 000000000..a764cc593 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktbase.c @@ -0,0 +1,297 @@ +/* + * lib/krb5/keytab/ktbase.c + * + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 2007 by 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. + * + * Registration functions for keytab. + */ + +#include "k5-int.h" +#include "k5-thread.h" +#include "kt-int.h" + +#ifndef LEAN_CLIENT + +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; +extern const krb5_kt_ops krb5_mkt_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_srvtab = { + &krb5_kts_ops, + NULL +}; +const static struct krb5_kt_typelist krb5_kt_typelist_memory = { + &krb5_mkt_ops, + &krb5_kt_typelist_srvtab +}; +const static struct krb5_kt_typelist krb5_kt_typelist_wrfile = { + &krb5_ktf_writable_ops, + &krb5_kt_typelist_memory +}; +const static struct krb5_kt_typelist krb5_kt_typelist_file = { + &krb5_ktf_ops, + &krb5_kt_typelist_wrfile +}; + +static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_file; +/* Lock for protecting the type list. */ +static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +int krb5int_kt_initialize(void) +{ + int err; + + err = k5_mutex_finish_init(&kt_typehead_lock); + if (err) + goto done; + err = krb5int_mkt_initialize(); + if (err) + goto done; + + done: + return(err); +} + +void +krb5int_kt_finalize(void) +{ + const struct krb5_kt_typelist *t, *t_next; + + k5_mutex_destroy(&kt_typehead_lock); + for (t = kt_typehead; t != &krb5_kt_typelist_file; t = t_next) { + t_next = t->next; + free((struct krb5_kt_typelist *)t); + } + + krb5int_mkt_finalize(); +} + + +/* + * 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 +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 = NULL; + unsigned int pfxlen; + const char *cp, *resid; + krb5_error_code err = 0; + + 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 if (name[0] == '/') { + 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) + goto cleanup; + 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) { + err = (*tlist->ops->resolve)(context, resid, ktid); + goto cleanup; + } + } + err = KRB5_KT_UNKNOWN_TYPE; + +cleanup: + free(pfx); + return err; +} + +/* + * 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)); +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktdefault.c b/krb5-1-7/src/lib/krb5/keytab/ktdefault.c new file mode 100644 index 000000000..3d7ee0946 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktdefault.c @@ -0,0 +1,46 @@ +/* + * lib/krb5/keytab/ktdefault.c + * + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#ifndef LEAN_CLIENT +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); +} + +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktfns.c b/krb5-1-7/src/lib/krb5/keytab/ktfns.c new file mode 100644 index 000000000..9239f3d16 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktfns.c @@ -0,0 +1,100 @@ +/* + * lib/krb5/keytab/ktfns.c + * + * Copyright 2001,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" + +const 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)); +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktfr_entry.c b/krb5-1-7/src/lib/krb5/keytab/ktfr_entry.c new file mode 100644 index 000000000..9587efc63 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktfr_entry.c @@ -0,0 +1,53 @@ +/* + * lib/krb5/keytab/ktfr_entry.c + * + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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() + */ +#ifndef LEAN_CLIENT + +#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) { + zap((char *)entry->key.contents, entry->key.length); + free(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); +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/ktremove.c b/krb5-1-7/src/lib/krb5/keytab/ktremove.c new file mode 100644 index 000000000..4ba6063f7 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/ktremove.c @@ -0,0 +1,42 @@ +/* + * lib/krb5/keytab/ktremove.c + * + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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() + */ +#ifndef LEAN_CLIENT + +#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; +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/read_servi.c b/krb5-1-7/src/lib/krb5/keytab/read_servi.c new file mode 100644 index 000000000..6638a5a92 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/read_servi.c @@ -0,0 +1,84 @@ +/* + * lib/krb5/keytab/read_servi.c + * + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ +#ifndef LEAN_CLIENT + +#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); +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/keytab/t_keytab.c b/krb5-1-7/src/lib/krb5/keytab/t_keytab.c new file mode 100644 index 000000000..d23502226 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/keytab/t_keytab.c @@ -0,0 +1,466 @@ +/* + * lib/krb5/keytab/t_keytab.c + * + * Copyright (C) 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. + * + * + * + * A set of tests for the keytab interface + */ + + +#include "k5-int.h" +#include "autoconf.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + + +int debug=0; + +extern const krb5_kt_ops krb5_ktf_writable_ops; + +#define KRB5_OK 0 + +#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); + +static void test_misc(krb5_context context) +{ + /* Tests for certain error returns */ + krb5_error_code kret; + krb5_keytab ktid; + char defname[BUFSIZ]; + char *name; + + fprintf(stderr, "Testing miscellaneous error conditions\n"); + + kret = krb5_kt_resolve(context, "unknown_method_ep:/tmp/name", &ktid); + if (kret != KRB5_KT_UNKNOWN_TYPE) { + CHECK(kret, "resolve unknown type"); + } + + /* Test length limits on krb5_kt_default_name */ + kret = krb5_kt_default_name(context, defname, sizeof(defname)); + CHECK(kret, "krb5_kt_default_name error"); + + /* Now allocate space - without the null... */ + name = malloc(strlen(defname)); + if(!name) { + fprintf(stderr, "Out of memory in testing\n"); + exit(1); + } + kret = krb5_kt_default_name(context, name, strlen(defname)); + free(name); + if (kret != KRB5_CONFIG_NOTENUFSPACE) { + CHECK(kret, "krb5_kt_default_name limited"); + } +} + +static void kt_test(krb5_context context, const char *name) +{ + krb5_error_code kret; + krb5_keytab kt; + const char *type; + char buf[BUFSIZ]; + char *p; + krb5_keytab_entry kent, kent2; + krb5_principal princ; + krb5_kt_cursor cursor, cursor2; + int cnt; + + kret = krb5_kt_resolve(context, name, &kt); + CHECK(kret, "resolve"); + + type = krb5_kt_get_type(context, kt); + CHECK_STR(type, "getting kt type"); + printf(" Type is: %s\n", type); + + kret = krb5_kt_get_name(context, kt, buf, sizeof(buf)); + CHECK(kret, "get_name"); + printf(" Name is: %s\n", buf); + + /* Check that length checks fail */ + /* The buffer is allocated too small - to allow for valgrind test of + overflows + */ + p = malloc(strlen(buf)); + kret = krb5_kt_get_name(context, kt, p, 1); + if(kret != KRB5_KT_NAME_TOOLONG) { + CHECK(kret, "get_name - size 1"); + } + + + kret = krb5_kt_get_name(context, kt, p, strlen(buf)); + if(kret != KRB5_KT_NAME_TOOLONG) { + CHECK(kret, "get_name"); + } + free(p); + + /* Try to lookup unknown principal - when keytab does not exist*/ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + if((kret != KRB5_KT_NOTFOUND) && (kret != ENOENT)) { + CHECK(kret, "Getting non-existant entry"); + } + + + /* =================== Add entries to keytab ================= */ + /* + * Add the following for this principal + * enctype 1, kvno 1, key = "1" + * enctype 2, kvno 1, key = "1" + * enctype 1, kvno 2, key = "2" + */ + memset(&kent, 0, sizeof(kent)); + kent.magic = KV5M_KEYTAB_ENTRY; + kent.principal = princ; + kent.timestamp = 327689; + kent.vno = 1; + kent.key.magic = KV5M_KEYBLOCK; + kent.key.enctype = 1; + kent.key.length = 1; + kent.key.contents = (krb5_octet *) "1"; + + + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding initial entry"); + + kent.key.enctype = 2; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding second entry"); + + kent.key.enctype = 1; + kent.vno = 2; + kent.key.contents = (krb5_octet *) "2"; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding third entry"); + + /* Free memory */ + krb5_free_principal(context, princ); + + /* ============== Test iterating over contents of keytab ========= */ + + kret = krb5_kt_start_seq_get(context, kt, &cursor); + CHECK(kret, "Start sequence get"); + + + memset(&kent, 0, sizeof(kent)); + cnt = 0; + while((kret = krb5_kt_next_entry(context, kt, &kent, &cursor)) == 0) { + if(((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Error in read contents\n"); + exit(1); + } + + if((kent.magic != KV5M_KEYTAB_ENTRY) || + (kent.key.magic != KV5M_KEYBLOCK)) { + fprintf(stderr, "Magic number in sequence not proper\n"); + exit(1); + } + + cnt++; + krb5_free_keytab_entry_contents(context, &kent); + } + if (kret != KRB5_KT_END) { + CHECK(kret, "getting next entry"); + } + + if(cnt != 3) { + fprintf(stderr, "Mismatch in number of entries in keytab"); + } + + kret = krb5_kt_end_seq_get(context, kt, &cursor); + CHECK(kret, "End sequence get"); + + + /* ========================== get_entry tests ============== */ + + /* Try to lookup unknown principal - now that keytab exists*/ + kret = krb5_parse_name(context, "test3/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + if((kret != KRB5_KT_NOTFOUND)) { + CHECK(kret, "Getting non-existant entry"); + } + + krb5_free_principal(context, princ); + + /* Try to lookup known principal */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify an enctype or kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + ((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + exit(1); + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup a specific enctype - but unspecified kvno - should give + * max kvno + */ + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did specified an enctype */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup unspecified enctype, but a specified kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 2, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify a kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + + /* Try to lookup specified enctype and kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 1, 1, &kent); + CHECK(kret, "looking up principal"); + + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + /* Try lookup with active iterators. */ + kret = krb5_kt_start_seq_get(context, kt, &cursor); + CHECK(kret, "Start sequence get(2)"); + kret = krb5_kt_start_seq_get(context, kt, &cursor2); + CHECK(kret, "Start sequence get(3)"); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(2)"); + krb5_free_keytab_entry_contents(context, &kent); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(3)"); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(4)"); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_get_entry(context, kt, kent.principal, 0, 0, &kent2); + CHECK(kret, "looking up principal(2)"); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(5)"); + if (!krb5_principal_compare(context, kent.principal, kent2.principal)) { + fprintf(stderr, "iterators not in sync\n"); + exit(1); + } + krb5_free_keytab_entry_contents(context, &kent); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(6)"); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(7)"); + krb5_free_keytab_entry_contents(context, &kent); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_end_seq_get(context, kt, &cursor); + CHECK(kret, "ending sequence get(1)"); + kret = krb5_kt_end_seq_get(context, kt, &cursor2); + CHECK(kret, "ending sequence get(2)"); + + /* Try to lookup specified enctype and kvno - that does not exist*/ + + kret = krb5_kt_get_entry(context, kt, princ, 3, 1, &kent); + if(kret != KRB5_KT_KVNONOTFOUND) { + CHECK(kret, "looking up specific principal, kvno, enctype"); + } + + krb5_free_principal(context, princ); + + + /* ========================= krb5_kt_remove_entry =========== */ + /* Lookup the keytab entry w/ 2 kvno - and delete version 2 - + ensure gone */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we are looking for max(kvno) and enc=1 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + /* Delete it */ + kret = krb5_kt_remove_entry(context, kt, &kent); + CHECK(kret, "Removing entry"); + + krb5_free_keytab_entry_contents(context, &kent); + /* And ensure gone */ + + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - kvno should now be 1 - we deleted 2 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Delete principal check failed\n"); + + exit(1); + + } + krb5_free_keytab_entry_contents(context, &kent); + + krb5_free_principal(context, princ); + + /* ======================= Finally close ======================= */ + + kret = krb5_kt_close(context, kt); + CHECK(kret, "close"); + +} + +static void do_test(krb5_context context, const char *prefix, + krb5_boolean delete) +{ + char *name, *filename; + + if (asprintf(&filename, "/tmp/kttest.%ld", (long) getpid()) < 0) { + perror("asprintf"); + exit(1); + } + if (asprintf(&name, "%s%s", prefix, filename) < 0) { + perror("asprintf"); + exit(1); + } + printf("Starting test on %s\n", name); + kt_test(context, name); + printf("Test on %s passed\n", name); + if(delete) + unlink(filename); + free(filename); + free(name); + +} + +int +main (void) +{ + krb5_context context; + krb5_error_code kret; + + + if ((kret = krb5_init_context(&context))) { + printf("Couldn't initialize krb5 library: %s\n", + error_message(kret)); + exit(1); + } + + /* All keytab types are registered by default -- test for + redundant error */ + kret = krb5_kt_register(context, &krb5_ktf_writable_ops); + if(kret && kret != KRB5_KT_TYPE_EXISTS) { + CHECK(kret, "register ktf_writable"); + } + + test_misc(context); + do_test(context, "WRFILE:", FALSE); + do_test(context, "MEMORY:", TRUE); + + krb5_free_context(context); + return 0; + +} + + +#if 0 +/* 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 * ); + + + +#endif diff --git a/krb5-1-7/src/lib/krb5/krb/Makefile.in b/krb5-1-7/src/lib/krb5/krb/Makefile.in new file mode 100644 index 000000000..db1f82372 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/Makefile.in @@ -0,0 +1,395 @@ +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 \ + fast.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 \ + pac.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 \ + 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)fast.$(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)pac.$(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)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)/fast.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)/pac.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)/t_ad_fx_armor.c \ + $(srcdir)/tgtname.c \ + $(srcdir)/unparse.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 \ + $(srcdir)/t_pac.c \ + $(srcdir)/t_princ.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 copy_data.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_PAC_OBJS= t_pac.o pac.o + +T_PRINC_OBJS= t_princ.o parse.o unparse.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_ad_fx_armor: t_ad_fx_armor.o + $(CC_LINK) -o $@ t_ad_fx_armor.o $(KRB5_BASE_LIBS) + +t_authdata: t_authdata.o copy_auth.o + $(CC_LINK) -o $@ t_authdata.o copy_auth.o $(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) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_ser $(T_SER_OBJS) $(KRB5_BASE_LIBS) + +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) + +t_pac: $(T_PAC_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_pac $(T_PAC_OBJS) $(KRB5_BASE_LIBS) + +t_princ: $(T_PRINC_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_princ $(T_PRINC_OBJS) $(KRB5_BASE_LIBS) + +TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \ + t_princ + +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 + KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) sh $(srcdir)/walktree-tests + KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) ./t_authdata + $(RUN_SETUP) $(VALGRIND) ./t_pac + $(RUN_SETUP) $(VALGRIND) ./t_princ + +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) \ + $(OUTPRE)t_authdata$(EXEEXT) $(OUTPRE)t_authdata.$(OBJEXT) + +@libobj_frag@ + diff --git a/krb5-1-7/src/lib/krb5/krb/addr_comp.c b/krb5-1-7/src/lib/krb5/krb/addr_comp.c new file mode 100644 index 000000000..16ab03bbf --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/addr_order.c b/krb5-1-7/src/lib/krb5/krb/addr_order.c new file mode 100644 index 000000000..2f01e1fbc --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/addr_srch.c b/krb5-1-7/src/lib/krb5/krb/addr_srch.c new file mode 100644 index 000000000..11a3ce0bb --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/addr_srch.c @@ -0,0 +1,68 @@ +/* + * 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" + +static unsigned int +address_count(krb5_address *const *addrlist) +{ + unsigned int i; + + if (addrlist == NULL) + return 0; + + for (i = 0; addrlist[i]; i++) + ; + + return i; +} + +/* + * 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) +{ + /* + * Treat an address list containing only a NetBIOS address + * as empty, because we presently have no way of associating + * a client with its NetBIOS address. + */ + if (address_count(addrlist) == 1 && + addrlist[0]->addrtype == ADDRTYPE_NETBIOS) + return TRUE; + if (!addrlist) + return TRUE; + for (; *addrlist; addrlist++) { + if (krb5_address_compare(context, addr, *addrlist)) + return TRUE; + } + return FALSE; +} diff --git a/krb5-1-7/src/lib/krb5/krb/appdefault.c b/krb5-1-7/src/lib/krb5/krb/appdefault.c new file mode 100644 index 000000000..94788899b --- /dev/null +++ b/krb5-1-7/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 +#include +#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 = + * } + * } + */ + + 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 = + * } + */ + + 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 = + */ + + 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 = + */ + + 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-7/src/lib/krb5/krb/auth_con.c b/krb5-1-7/src/lib/krb5/krb/auth_con.c new file mode 100644 index 000000000..8ef767a85 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/auth_con.c @@ -0,0 +1,570 @@ +#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))) { + free(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)calloc(1, sizeof(struct _krb5_auth_context)); + if (!*auth_context) + return ENOMEM; + + /* 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)->negotiated_etype = ENCTYPE_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 == NULL) + return 0; + 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) + free(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; +} +#ifndef LEAN_CLIENT +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)); +} +#endif + +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)calloc(1,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) + free(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; +} + +krb5_error_code +krb5_auth_con_get_subkey_enctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + *etype = auth_context->negotiated_etype; + return 0; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/auth_con.h b/krb5-1-7/src/lib/krb5/krb/auth_con.h new file mode 100644 index 000000000..be63bedbf --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/auth_con.h @@ -0,0 +1,37 @@ + +#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; + krb5_enctype negotiated_etype; +}; + + +/* 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-7/src/lib/krb5/krb/bld_pr_ext.c b/krb5-1-7/src/lib/krb5/krb/bld_pr_ext.c new file mode 100644 index 000000000..1a288c896 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/bld_pr_ext.c @@ -0,0 +1,95 @@ +/* + * lib/krb5/krb/bld_pr_ext.c + * + * Copyright 1991, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +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; + int i, count = 0; + krb5_data *princ_data; + krb5_principal princ_ret; + krb5_data tmpdata; + + 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) { + free(princ_data); + return ENOMEM; + } + princ_ret->data = princ_data; + princ_ret->length = count; + tmpdata.length = rlen; + tmpdata.data = (char *) realm; + if (krb5int_copy_data_contents_add0(context, &tmpdata, &princ_ret->realm) != 0) { + free(princ_data); + free(princ_ret); + return ENOMEM; + } + + /* process rest of components */ + va_start(ap, realm); + for (i = 0; i < count; i++) { + tmpdata.length = va_arg(ap, unsigned int); + tmpdata.data = va_arg(ap, char *); + if (krb5int_copy_data_contents_add0(context, &tmpdata, + &princ_data[i]) != 0) + goto free_out; + } + va_end(ap); + *princ = princ_ret; + krb5_princ_type(context, princ_ret) = KRB5_NT_UNKNOWN; + return 0; + +free_out: + while (--i >= 0) + free(princ_data[i].data); + free(princ_data); + free(princ_ret->realm.data); + free(princ_ret); + va_end(ap); + return ENOMEM; +} diff --git a/krb5-1-7/src/lib/krb5/krb/bld_princ.c b/krb5-1-7/src/lib/krb5/krb/bld_princ.c new file mode 100644 index 000000000..d3e0d294b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/bld_princ.c @@ -0,0 +1,188 @@ +/* + * 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 +#include "k5-int.h" + +/* Takes first component as argument for KIM API, + * which does not allow realms with zero components */ +static krb5_error_code +krb5int_build_principal_va(krb5_context context, + krb5_principal princ, + unsigned int rlen, + const char *realm, + const char *first, + va_list ap) +{ + krb5_error_code retval = 0; + char *r = NULL; + krb5_data *data = NULL; + krb5_int32 count = 0; + krb5_int32 size = 2; /* initial guess at needed space */ + char *component = NULL; + + data = malloc(size * sizeof(krb5_data)); + if (!data) { retval = ENOMEM; } + + if (!retval) { + r = strdup(realm); + if (!r) { retval = ENOMEM; } + } + + if (!retval && first) { + data[0].length = strlen(first); + data[0].data = strdup(first); + if (!data[0].data) { retval = ENOMEM; } + count++; + + /* ap is only valid if first is non-NULL */ + while (!retval && (component = va_arg(ap, char *))) { + if (count == size) { + krb5_data *new_data = NULL; + + size *= 2; + new_data = realloc ((char *) data, sizeof(krb5_data) * size); + if (new_data) { + data = new_data; + } else { + retval = ENOMEM; + } + } + + if (!retval) { + data[count].length = strlen(component); + data[count].data = strdup(component); + if (!data[count].data) { retval = ENOMEM; } + count++; + } + } + } + + if (!retval) { + princ->type = KRB5_NT_UNKNOWN; + princ->magic = KV5M_PRINCIPAL; + krb5_princ_set_realm_data(context, princ, r); + krb5_princ_set_realm_length(context, princ, rlen); + princ->data = data; + princ->length = count; + r = NULL; /* take ownership */ + data = NULL; /* take ownership */ + } + + if (data) { + while (--count >= 0) { + free(data[count].data); + } + free(data); + } + free(r); + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_build_principal_va(krb5_context context, + krb5_principal princ, + unsigned int rlen, + const char *realm, + va_list ap) +{ + char *first = va_arg(ap, char *); + + return krb5int_build_principal_va(context, princ, rlen, realm, first, ap); +} + +/* Takes first component as argument for KIM API, + * which does not allow realms with zero components */ +krb5_error_code KRB5_CALLCONV +krb5int_build_principal_alloc_va(krb5_context context, + krb5_principal *princ, + unsigned int rlen, + const char *realm, + const char *first, + va_list ap) +{ + krb5_error_code retval = 0; + + krb5_principal p = malloc(sizeof(krb5_principal_data)); + if (!p) { retval = ENOMEM; } + + if (!retval) { + retval = krb5int_build_principal_va(context, p, rlen, realm, first, ap); + } + + if (!retval) { + *princ = p; + } else { + free(p); + } + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_build_principal_alloc_va(krb5_context context, + krb5_principal *princ, + unsigned int rlen, + const char *realm, + va_list ap) +{ + krb5_error_code retval = 0; + + krb5_principal p = malloc(sizeof(krb5_principal_data)); + if (!p) { retval = ENOMEM; } + + if (!retval) { + retval = krb5_build_principal_va(context, p, rlen, realm, ap); + } + + if (!retval) { + *princ = p; + } else { + free(p); + } + + return retval; +} + +krb5_error_code KRB5_CALLCONV_C +krb5_build_principal(krb5_context context, + krb5_principal * princ, + unsigned int rlen, + const char * realm, ...) +{ + krb5_error_code retval = 0; + va_list ap; + + va_start(ap, realm); + retval = krb5_build_principal_alloc_va(context, princ, rlen, realm, ap); + va_end(ap); + + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/brand.c b/krb5-1-7/src/lib/krb5/krb/brand.c new file mode 100644 index 000000000..7e4e0dbd0 --- /dev/null +++ b/krb5-1-7/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: " */ + +#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-7/src/lib/krb5/krb/chk_trans.c b/krb5-1-7/src/lib/krb5/krb/chk_trans.c new file mode 100644 index 000000000..9af063ce3 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/chk_trans.c @@ -0,0 +1,434 @@ +/* + * lib/krb5/krb/chk_trans.c + * + * Copyright 2001, 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. + * + * + * krb5_check_transited_list() + */ +#include "k5-int.h" +#include + +#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, unsigned 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 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 (data_eq (*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-7/src/lib/krb5/krb/chpw.c b/krb5-1-7/src/lib/krb5/krb/chpw.c new file mode 100644 index 000000000..9c3a95a8c --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/chpw.c @@ -0,0 +1,539 @@ +/* +** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc. +*/ +#include + +#include "k5-int.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 */ + + store_16_be(packet->length, ptr); + ptr += 2; + + /* version == 0x0001 big-endian */ + + *ptr++ = 0; + *ptr++ = 1; + + /* ap_req length, big-endian */ + + store_16_be(ap_req->length, ptr); + ptr += 2; + + /* 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 = NULL; + 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) { + free(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; + struct krb5_setpw_req req; + + char *ptr; + + cipherpw.data = NULL; + cipherpw.length = 0; + + if ((ret = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE))) + return(ret); + + req.target = targprinc; + req.password.data = passwd; + req.password.length = strlen(passwd); + ret = encode_krb5_setpw_req(&req, &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 */ + store_16_be(packet->length, ptr); + ptr += 2; + /* put in the version */ + *ptr++ = (char)0xff; + *ptr++ = (char)0x80; + /* the ap_req length is big endian */ + store_16_be(ap_req->length, ptr); + ptr += 2; + /* 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"; + break; + default: + *code_string = "Password change failed"; + break; + } + + return(0); +} + diff --git a/krb5-1-7/src/lib/krb5/krb/cleanup.h b/krb5-1-7/src/lib/krb5/krb/cleanup.h new file mode 100644 index 000000000..94b39f757 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/conv_creds.c b/krb5-1-7/src/lib/krb5/krb/conv_creds.c new file mode 100644 index 000000000..b6c610842 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/conv_creds.c @@ -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. + */ + +#include "k5-int.h" +#include +#include +#include +#include "port-sockets.h" +#include "socket-utils.h" + +krb5_error_code KRB5_CALLCONV +krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds, + struct credentials *v4creds) +{ + return KRB524_KRB4_DISABLED; +} + +/* 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 KRB524_KRB4_DISABLED; +} + +void KRB5_CALLCONV krb524_init_ets () +{ +} +#endif diff --git a/krb5-1-7/src/lib/krb5/krb/conv_princ.c b/krb5-1-7/src/lib/krb5/krb/conv_princ.c new file mode 100644 index 000000000..3247893bc --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/conv_princ.c @@ -0,0 +1,353 @@ +/* + * 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 +#include + +/* 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 int 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 (strlcpy(name, p->v4_str, ANAME_SZ) >= ANAME_SZ) + return KRB5_INVALID_PRINCIPAL; + 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, KRB5_CONF_REALMS, + tmp_prealm, KRB5_CONF_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] = KRB5_CONF_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] = KRB5_CONF_REALMS; + names [1] = realm_name; + names [2] = KRB5_CONF_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] = KRB5_CONF_REALMS; + names[1] = realm; + names[2] = KRB5_CONF_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)); + free(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-7/src/lib/krb5/krb/copy_addrs.c b/krb5-1-7/src/lib/krb5/krb/copy_addrs.c new file mode 100644 index 000000000..f3f75c33b --- /dev/null +++ b/krb5-1-7/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))) { + free(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-7/src/lib/krb5/krb/copy_athctr.c b/krb5-1-7/src/lib/krb5/krb/copy_athctr.c new file mode 100644 index 000000000..c356fbf78 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/copy_athctr.c @@ -0,0 +1,83 @@ +/* + * 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" +#ifndef LEAN_CLIENT +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) { + free(tempto); + return retval; + } + + if (authfrom->checksum && + (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) { + krb5_free_principal(context, tempto->client); + free(tempto); + return retval; + } + + if (authfrom->subkey) { + retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey); + if (retval) { + free(tempto->subkey); + krb5_free_checksum(context, tempto->checksum); + krb5_free_principal(context, tempto->client); + free(tempto); + return retval; + } + } + + if (authfrom->authorization_data) { + retval = krb5_copy_authdata(context, authfrom->authorization_data, + &tempto->authorization_data); + if (retval) { + free(tempto->subkey); + krb5_free_checksum(context, tempto->checksum); + krb5_free_principal(context, tempto->client); + krb5_free_authdata(context, tempto->authorization_data); + free(tempto); + return retval; + } + } + + *authto = tempto; + return 0; +} +#endif + diff --git a/krb5-1-7/src/lib/krb5/krb/copy_auth.c b/krb5-1-7/src/lib/krb5/krb/copy_auth.c new file mode 100644 index 000000000..ca3fb0366 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/copy_auth.c @@ -0,0 +1,278 @@ +/* + * 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() + */ +/* + * Copyright (c) 2006-2008, 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" + +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))) { + free(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_merge_authdata(krb5_context context, krb5_authdata *const *inauthdat1, krb5_authdata * const *inauthdat2, + krb5_authdata ***outauthdat) +{ + krb5_error_code retval; + krb5_authdata ** tempauthdat; + register unsigned int nelems = 0, nelems2 = 0; + + *outauthdat = NULL; + if (!inauthdat1 && !inauthdat2) { + *outauthdat = 0; + return 0; + } + + if (inauthdat1) + while (inauthdat1[nelems]) nelems++; + if (inauthdat2) + while (inauthdat2[nelems2]) nelems2++; + + /* one more for a null terminated list */ + if (!(tempauthdat = (krb5_authdata **) calloc(nelems+nelems2+1, + sizeof(*tempauthdat)))) + return ENOMEM; + + if (inauthdat1) { + for (nelems = 0; inauthdat1[nelems]; nelems++) { + retval = krb5_copy_authdatum(context, inauthdat1[nelems], + &tempauthdat[nelems]); + if (retval) { + krb5_free_authdata(context, tempauthdat); + return retval; + } + } + } + + if (inauthdat2) { + for (nelems2 = 0; inauthdat2[nelems2]; nelems2++) { + retval = krb5_copy_authdatum(context, inauthdat2[nelems2], + &tempauthdat[nelems++]); + if (retval) { + krb5_free_authdata(context, tempauthdat); + return retval; + } + } + } + + *outauthdat = tempauthdat; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_copy_authdata(krb5_context context, + krb5_authdata *const *in_authdat, krb5_authdata ***out) +{ + return krb5_merge_authdata(context, in_authdat, NULL, out); +} + +krb5_error_code KRB5_CALLCONV +krb5_decode_authdata_container(krb5_context context, + krb5_authdatatype type, + const krb5_authdata *container, + krb5_authdata ***authdata) +{ + krb5_error_code code; + krb5_data data; + + *authdata = NULL; + + if ((container->ad_type & AD_TYPE_FIELD_TYPE_MASK) != type) + return EINVAL; + + data.length = container->length; + data.data = (char *)container->contents; + + code = decode_krb5_authdata(&data, authdata); + if (code) + return code; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_encode_authdata_container(krb5_context context, + krb5_authdatatype type, + krb5_authdata *const*authdata, + krb5_authdata ***container) +{ + krb5_error_code code; + krb5_data *data; + krb5_authdata ad_datum; + krb5_authdata *ad_data[2]; + + *container = NULL; + + code = encode_krb5_authdata((krb5_authdata * const *)authdata, &data); + if (code) + return code; + + ad_datum.ad_type = type & AD_TYPE_FIELD_TYPE_MASK; + ad_datum.length = data->length; + ad_datum.contents = (unsigned char *)data->data; + + ad_data[0] = &ad_datum; + ad_data[1] = NULL; + + code = krb5_copy_authdata(context, ad_data, container); + + krb5_free_data(context, data); + + return code; +} + +struct find_authdata_context { + krb5_authdata **out; + size_t space; + size_t length; +}; + +static krb5_error_code grow_find_authdata +(krb5_context context, struct find_authdata_context *fctx, + krb5_authdata *elem) +{ + krb5_error_code retval = 0; + if (fctx->length == fctx->space) { + krb5_authdata **new; + if (fctx->space >= 256) { + krb5_set_error_message(context, ERANGE, "More than 256 authdata matched a query"); + return ERANGE; + } + new = realloc(fctx->out, + sizeof (krb5_authdata *)*(2*fctx->space+1)); + if (new == NULL) + return ENOMEM; + fctx->out = new; + fctx->space *=2; + } + fctx->out[fctx->length+1] = NULL; + retval = krb5_copy_authdatum(context, elem, + &fctx->out[fctx->length]); + if (retval == 0) + fctx->length++; + return retval; +} + + + + +static krb5_error_code find_authdata_1 +(krb5_context context, krb5_authdata *const *in_authdat, krb5_authdatatype ad_type, + struct find_authdata_context *fctx) +{ + int i = 0; + krb5_error_code retval=0; + + for (i = 0; in_authdat[i]; i++) { + krb5_authdata *ad = in_authdat[i]; + if (ad->ad_type == ad_type && retval ==0) + retval = grow_find_authdata(context, fctx, ad); + else switch (ad->ad_type) { + krb5_authdata **decoded_container; + case KRB5_AUTHDATA_IF_RELEVANT: + if (retval == 0) + retval = krb5_decode_authdata_container( context, ad->ad_type, ad, &decoded_container); + if (retval == 0) { + retval = find_authdata_1(context, + decoded_container, ad_type, fctx); + krb5_free_authdata(context, decoded_container); + } + break; + default: + break; + } + } + return retval; +} + + +krb5_error_code krb5int_find_authdata +(krb5_context context, krb5_authdata *const * ticket_authdata, + krb5_authdata * const *ap_req_authdata, + krb5_authdatatype ad_type, + krb5_authdata ***results) +{ + krb5_error_code retval = 0; + struct find_authdata_context fctx; + fctx.length = 0; + fctx.space = 2; + fctx.out = calloc(fctx.space+1, sizeof (krb5_authdata *)); + *results = NULL; + if (fctx.out == NULL) + return ENOMEM; + if (ticket_authdata) + retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx); + if ((retval==0) && ap_req_authdata) + retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx); + if ((retval== 0) && fctx.length) + *results = fctx.out; + else krb5_free_authdata(context, fctx.out); + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/copy_cksum.c b/krb5-1-7/src/lib/krb5/krb/copy_cksum.c new file mode 100644 index 000000000..2bff2c36e --- /dev/null +++ b/krb5-1-7/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))) { + free(tempto); + return ENOMEM; + } + memcpy((char *) tempto->contents, (char *) ckfrom->contents, + ckfrom->length); + + *ckto = tempto; + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/copy_creds.c b/krb5-1-7/src/lib/krb5/krb/copy_creds.c new file mode 100644 index 000000000..e6fece383 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/copy_creds.c @@ -0,0 +1,116 @@ +/* + * 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; + + if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred)))) + return ENOMEM; + + retval = krb5int_copy_creds_contents(context, incred, tempcred); + if (retval) + free(tempcred); + else + *outcred = tempcred; + return retval; +} + +/* + * Copy contents of input credentials structure to supplied + * destination, allocating storage for indirect fields as needed. On + * success, the output is a deep copy of the input. On error, the + * output structure is garbage and its contents should be ignored. + */ +krb5_error_code +krb5int_copy_creds_contents(krb5_context context, const krb5_creds *incred, + krb5_creds *tempcred) +{ + krb5_error_code retval; + krb5_data *scratch; + + *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; + free(scratch); + retval = krb5_copy_data(context, &incred->second_ticket, &scratch); + if (retval) + goto clearticket; + + tempcred->second_ticket = *scratch; + free(scratch); + + retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata); + if (retval) + goto clearsecondticket; + + return 0; + + clearsecondticket: + memset(tempcred->second_ticket.data,0,tempcred->second_ticket.length); + free(tempcred->second_ticket.data); + clearticket: + memset(tempcred->ticket.data,0,tempcred->ticket.length); + free(tempcred->ticket.data); + cleanaddrs: + krb5_free_addresses(context, tempcred->addresses); + cleanblock: + free(tempcred->keyblock.contents); + cleanserver: + krb5_free_principal(context, tempcred->server); + cleanclient: + krb5_free_principal(context, tempcred->client); + cleanlast: + /* Do not free tempcred - we did not allocate it - its contents are + garbage - but we should not free it */ + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/copy_data.c b/krb5-1-7/src/lib/krb5/krb/copy_data.c new file mode 100644 index 000000000..6a2772c79 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/copy_data.c @@ -0,0 +1,96 @@ +/* + * lib/krb5/krb/copy_data.c + * + * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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; + krb5_error_code retval; + + if (!indata) { + *outdata = 0; + return 0; + } + + if (!(tempdata = (krb5_data *)malloc(sizeof(*tempdata)))) + return ENOMEM; + + retval = krb5int_copy_data_contents(context, indata, tempdata); + if (retval) { + free(tempdata); + return retval; + } + + *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; +} + +/* As above, but add an (uncounted) extra byte at the end to + null-terminate the data so it can be used as a standard C + string. */ +krb5_error_code +krb5int_copy_data_contents_add0(krb5_context context, const krb5_data *indata, krb5_data *outdata) +{ + if (!indata) + return EINVAL; + outdata->length = indata->length; + if (!(outdata->data = malloc(outdata->length + 1))) + return ENOMEM; + if (outdata->length) + memcpy(outdata->data, indata->data, outdata->length); + outdata->data[outdata->length] = 0; + outdata->magic = KV5M_DATA; + + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/copy_key.c b/krb5-1-7/src/lib/krb5/krb/copy_key.c new file mode 100644 index 000000000..e7fc2772a --- /dev/null +++ b/krb5-1-7/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))) { + free(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-7/src/lib/krb5/krb/copy_princ.c b/krb5-1-7/src/lib/krb5/krb/copy_princ.c new file mode 100644 index 000000000..c976108dc --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/copy_princ.c @@ -0,0 +1,79 @@ +/* + * lib/krb5/krb/copy_princ.c + * + * Copyright 1990, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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++) { + if (krb5int_copy_data_contents(context, + krb5_princ_component(context, inprinc, i), + krb5_princ_component(context, tempprinc, i)) != 0) { + while (--i >= 0) + free(krb5_princ_component(context, tempprinc, i)->data); + free (tempprinc->data); + free (tempprinc); + return ENOMEM; + } + } + + if (krb5int_copy_data_contents_add0(context, &inprinc->realm, + &tempprinc->realm) != 0) { + for (i = 0; i < nelems; i++) + free(krb5_princ_component(context, tempprinc, i)->data); + free(tempprinc->data); + free(tempprinc); + return ENOMEM; + } + + *outprinc = tempprinc; + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/copy_tick.c b/krb5-1-7/src/lib/krb5/krb/copy_tick.c new file mode 100644 index 000000000..76d8bcfac --- /dev/null +++ b/krb5-1-7/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) { + free(tempto); + return retval; + } + retval = krb5_copy_principal(context, partfrom->client, &tempto->client); + if (retval) { + krb5_free_keyblock(context, tempto->session); + free(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); + free(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) { + free(tempto->transited.tr_contents.data); + krb5_free_principal(context, tempto->client); + krb5_free_keyblock(context, tempto->session); + free(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); + free(tempto->transited.tr_contents.data); + krb5_free_principal(context, tempto->client); + krb5_free_keyblock(context, tempto->session); + free(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) { + free(tempto); + return retval; + } + retval = krb5_copy_data(context, &from->enc_part.ciphertext, &scratch); + if (retval) { + krb5_free_principal(context, tempto->server); + free(tempto); + return retval; + } + tempto->enc_part.ciphertext = *scratch; + free(scratch); + retval = krb5_copy_enc_tkt_part(context, from->enc_part2, &tempto->enc_part2); + if (retval) { + free(tempto->enc_part.ciphertext.data); + krb5_free_principal(context, tempto->server); + free(tempto); + return retval; + } + *pto = tempto; + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/cp_key_cnt.c b/krb5-1-7/src/lib/krb5/krb/cp_key_cnt.c new file mode 100644 index 000000000..150be0a57 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/decode_kdc.c b/krb5-1-7/src/lib/krb5/krb/decode_kdc.c new file mode 100644 index 000000000..689e2a241 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/decode_kdc.c @@ -0,0 +1,70 @@ +/* + * 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 +krb5int_decode_tgs_rep(krb5_context context, krb5_data *enc_rep, const krb5_keyblock *key, + krb5_keyusage usage, krb5_kdc_rep **dec_rep) +{ + krb5_error_code retval; + krb5_kdc_rep *local_dec_rep; + + if (krb5_is_as_rep(enc_rep)) { + retval = decode_krb5_as_rep(enc_rep, &local_dec_rep); + } else if (krb5_is_tgs_rep(enc_rep)) { + 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-7/src/lib/krb5/krb/decrypt_tk.c b/krb5-1-7/src/lib/krb5/krb/decrypt_tk.c new file mode 100644 index 000000000..36ecbb45b --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/deltat.c b/krb5-1-7/src/lib/krb5/krb/deltat.c new file mode 100644 index 000000000..2541591f8 --- /dev/null +++ b/krb5-1-7/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 +#include +#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 /* 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 /* 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 /* 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-7/src/lib/krb5/krb/deps b/krb5-1-7/src/lib/krb5/krb/deps new file mode 100644 index 000000000..9f9102427 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/deps @@ -0,0 +1,945 @@ +# +# Generated makefile dependencies follow. +# +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +fast.so fast.po $(OUTPRE)fast.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + fast.c fast.h int-proto.h +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 int-proto.h +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 \ + fast.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 +pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-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-utf8.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h pac.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h fast.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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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-unicode.h $(SRCTOP)/include/k5-utf8.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-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 +t_ad_fx_armor.so t_ad_fx_armor.po $(OUTPRE)t_ad_fx_armor.$(OBJEXT): \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) t_ad_fx_armor.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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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 +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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/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 +t_pac.so t_pac.po $(OUTPRE)t_pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_pac.c +t_princ.so t_princ.po $(OUTPRE)t_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-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/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_princ.c diff --git a/krb5-1-7/src/lib/krb5/krb/enc_helper.c b/krb5-1-7/src/lib/krb5/krb/enc_helper.c new file mode 100644 index 000000000..63e3495da --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/encode_kdc.c b/krb5-1-7/src/lib/krb5/krb/encode_kdc.c new file mode 100644 index 000000000..8b879c015 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/encrypt_tk.c b/krb5-1-7/src/lib/krb5/krb/encrypt_tk.c new file mode 100644 index 000000000..ed2b8c1b8 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/fast.c b/krb5-1-7/src/lib/krb5/krb/fast.c new file mode 100644 index 000000000..5231065fe --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/fast.c @@ -0,0 +1,524 @@ +/* + * lib/krb5/krb/fast.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +/* + * It is possible to support sending a request that includes both a + * FAST and normal version. This would complicate the + * pre-authentication logic significantly. You would need to maintain + * two contexts, one for FAST and one for normal use. In adition, you + * would need to manage the security issues surrounding downgrades. + * However trying FAST at all requires an armor key. Generally in + * obtaining the armor key, the client learns enough to know that FAST + * is supported. If not, the client can see FAST in the + * preauth_required error's padata and retry with FAST. So, this + * implementation does not support FAST+normal. + * + * We store the outer version of the request to use . The caller + * stores the inner version. We handle the encoding of the request + * body (and request) and provide encoded request bodies for the + * caller to use as these may be used for checksums. In the AS case + * we also evaluate whether to continue a conversation as one of the + * important questions there is the presence of a cookie. + */ +#include "fast.h" +#include "int-proto.h" + + +static krb5_error_code fast_armor_ap_request +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_ccache ccache, krb5_data *target_realm) +{ + krb5_error_code retval = 0; + krb5_creds creds, *out_creds = NULL; + krb5_auth_context authcontext = NULL; + krb5_data encoded_authenticator; + krb5_fast_armor *armor = NULL; + krb5_keyblock *subkey = NULL, *armor_key = NULL; + encoded_authenticator.data = NULL; + memset(&creds, 0, sizeof(creds)); + retval = krb5_tgtname(context, target_realm, target_realm, &creds.server); + if (retval ==0) + retval = krb5_cc_get_principal(context, ccache, &creds.client); + if (retval == 0) + retval = krb5_get_credentials(context, 0, ccache, &creds, &out_creds); + if (retval == 0) + retval = krb5_mk_req_extended(context, &authcontext, AP_OPTS_USE_SUBKEY, NULL /*data*/, + out_creds, &encoded_authenticator); + if (retval == 0) + retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey); + if (retval == 0) + retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", + &out_creds->keyblock, "ticketarmor", &armor_key); + if (retval == 0) { + armor = calloc(1, sizeof(krb5_fast_armor)); + if (armor == NULL) + retval = ENOMEM; + } + if (retval == 0) { + armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST; + armor->armor_value = encoded_authenticator; + encoded_authenticator.data = NULL; + encoded_authenticator.length = 0; + state->armor = armor; + armor = NULL; + state->armor_key = armor_key; + armor_key = NULL; + } + krb5_free_keyblock(context, armor_key); + krb5_free_keyblock(context, subkey); + if (out_creds) + krb5_free_creds(context, out_creds); + krb5_free_cred_contents(context, &creds); + if (encoded_authenticator.data) + krb5_free_data_contents(context, &encoded_authenticator); + krb5_auth_con_free(context, authcontext); + return retval; +} + +krb5_error_code +krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_req *request, krb5_data **encoded_request_body) +{ + krb5_error_code retval = 0; + krb5_data *local_encoded_request_body = NULL; + assert(state != NULL); + *encoded_request_body = NULL; + if (state->armor_key == NULL) { + return encode_krb5_kdc_req_body(request, encoded_request_body); + } + state->fast_outer_request = *request; + state->fast_outer_request.padata = NULL; + if (retval == 0) + retval = encode_krb5_kdc_req_body(&state->fast_outer_request, + &local_encoded_request_body); + if (retval == 0) { + *encoded_request_body = local_encoded_request_body; + local_encoded_request_body = NULL; + } + if (local_encoded_request_body != NULL) + krb5_free_data(context, local_encoded_request_body); + return retval; +} + +krb5_error_code krb5int_fast_as_armor +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_gic_opt_ext *opte, + krb5_kdc_req *request) +{ + krb5_error_code retval = 0; + krb5_ccache ccache = NULL; + krb5_clear_error_message(context); + if (opte->opt_private->fast_ccache_name) { + retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name, + &ccache); + if (retval==0) + retval = fast_armor_ap_request(context, state, ccache, + krb5_princ_realm(context, request->server)); + if (retval != 0) { + const char * errmsg; + errmsg = krb5_get_error_message(context, retval); + if (errmsg) { + krb5_set_error_message(context, retval, "%s constructing AP-REQ armor", errmsg); + krb5_free_error_message(context, errmsg); + } + } + } + if (ccache) + krb5_cc_close(context, ccache); + return retval; +} + + +krb5_error_code +krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + const krb5_data *to_be_checksummed, kdc_req_encoder_proc encoder, + krb5_data **encoded_request) +{ + krb5_error_code retval = 0; + krb5_pa_data *pa_array[2]; + krb5_pa_data pa[2]; + krb5_fast_req fast_req; + krb5_fast_armored_req *armored_req = NULL; + krb5_data *encoded_fast_req = NULL; + krb5_data *encoded_armored_req = NULL; + krb5_data *local_encoded_result = NULL; + krb5_cksumtype cksumtype; + krb5_data random_data; + char random_buf[4]; + + + assert(state != NULL); + assert(state->fast_outer_request.padata == NULL); + memset(pa_array, 0, sizeof pa_array); + if (state->armor_key == NULL) { + return encoder(request, encoded_request); + } +/* Fill in a fresh random nonce for each inner request*/ + random_data.length = 4; + random_data.data = (char *)random_buf; + retval = krb5_c_random_make_octets(context, &random_data); + if (retval == 0) { + request->nonce = 0x7fffffff & load_32_n(random_buf); + state->nonce = request->nonce; + } + fast_req.req_body = request; + if (fast_req.req_body->padata == NULL) { + fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *)); + if (fast_req.req_body->padata == NULL) + retval = ENOMEM; + } + fast_req.fast_options = state->fast_options; + if (retval == 0) + retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req); + if (retval == 0) { + armored_req = calloc(1, sizeof(krb5_fast_armored_req)); + if (armored_req == NULL) + retval = ENOMEM; + } + if (retval == 0) + armored_req->armor = state->armor; + if (retval == 0) + retval = krb5int_c_mandatory_cksumtype(context, state->armor_key->enctype, + &cksumtype); + /* DES enctypes have unkeyed mandatory checksums; need a keyed one. */ + if (retval == 0 && !krb5_c_is_keyed_cksum(cksumtype)) + cksumtype = CKSUMTYPE_RSA_MD5_DES; + if (retval ==0) + retval = krb5_c_make_checksum(context, cksumtype, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, to_be_checksummed, + &armored_req->req_checksum); + if (retval == 0) + retval = krb5_encrypt_helper(context, state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req, + &armored_req->enc_part); + if (retval == 0) + retval = encode_krb5_pa_fx_fast_request(armored_req, &encoded_armored_req); + if (retval==0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].contents = (unsigned char *) encoded_armored_req->data; + pa[0].length = encoded_armored_req->length; + pa_array[0] = &pa[0]; + } + state->fast_outer_request.padata = pa_array; + if(retval == 0) + retval = encoder(&state->fast_outer_request, &local_encoded_result); + if (retval == 0) { + *encoded_request = local_encoded_result; + local_encoded_result = NULL; + } + if (encoded_armored_req) + krb5_free_data(context, encoded_armored_req); + if (armored_req) { + armored_req->armor = NULL; /*owned by state*/ + krb5_free_fast_armored_req(context, armored_req); + } + if (encoded_fast_req) + krb5_free_data(context, encoded_fast_req); + if (local_encoded_result) + krb5_free_data(context, local_encoded_result); + state->fast_outer_request.padata = NULL; + return retval; +} + +static krb5_error_code decrypt_fast_reply +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_pa_data **in_padata, + krb5_fast_response **response) +{ + krb5_error_code retval = 0; + krb5_data scratch; + krb5_enc_data *encrypted_response = NULL; + krb5_pa_data *fx_reply = NULL; + krb5_fast_response *local_resp = NULL; + assert(state != NULL); + assert(state->armor_key); + fx_reply = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FX_FAST); + if (fx_reply == NULL) + retval = KRB5_ERR_FAST_REQUIRED; + if (retval == 0) { + scratch.data = (char *) fx_reply->contents; + scratch.length = fx_reply->length; + retval = decode_krb5_pa_fx_fast_reply(&scratch, &encrypted_response); + } + scratch.data = NULL; + if (retval == 0) { + scratch.data = malloc(encrypted_response->ciphertext.length); + if (scratch.data == NULL) + retval = ENOMEM; + scratch.length = encrypted_response->ciphertext.length; + } + if (retval == 0) + retval = krb5_c_decrypt(context, state->armor_key, + KRB5_KEYUSAGE_FAST_REP, NULL, + encrypted_response, &scratch); + if (retval != 0) { + const char * errmsg; + errmsg = krb5_get_error_message(context, retval); + krb5_set_error_message(context, retval, "%s while decrypting FAST reply", errmsg); + krb5_free_error_message(context, errmsg); + } + if (retval == 0) + retval = decode_krb5_fast_response(&scratch, &local_resp); + if (retval == 0) { + if (local_resp->nonce != state->nonce) { + retval = KRB5_KDCREP_MODIFIED; + krb5_set_error_message(context, retval, "nonce modified in FAST response: KDC response modified"); + } + } + if (retval == 0) { + *response = local_resp; + local_resp = NULL; + } + if (scratch.data) + free(scratch.data); + if (encrypted_response) + krb5_free_enc_data(context, encrypted_response); + if (local_resp) + krb5_free_fast_response(context, local_resp); + return retval; +} + +/* + * FAST separates two concepts: the set of padata we're using to + * decide what pre-auth mechanisms to use and the set of padata we're + * making available to mechanisms in order for them to respond to an + * error. The plugin interface in March 2009 does not permit + * separating these concepts for the plugins. This function makes + * both available for future revisions to the plugin interface. It + * also re-encodes the padata from the current error as a encoded + * typed-data and puts that in the e_data field. That will allow + * existing plugins with the old interface to find the error data. + * The output parameter out_padata contains the padata from the error + * whenever padata is available (all the time with fast). + */ +krb5_error_code +krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_state *state, + krb5_error **err_replyptr , krb5_pa_data ***out_padata, + krb5_boolean *retry) +{ + krb5_error_code retval = 0; + krb5_error *err_reply = *err_replyptr; + *out_padata = NULL; + *retry = 0; + if (state->armor_key) { + krb5_pa_data *fx_error_pa; + krb5_pa_data **result = NULL; + krb5_data scratch, *encoded_td = NULL; + krb5_error *fx_error = NULL; + krb5_fast_response *fast_response = NULL; + retval = decode_krb5_padata_sequence(&err_reply->e_data, &result); + if (retval == 0) + retval = decrypt_fast_reply(context, state, result, &fast_response); + if (retval) { + /*This can happen if the KDC does not understand FAST. We + * don't expect that, but treating it as the fatal error + * indicated by the KDC seems reasonable. + */ + *retry = 0; + krb5_free_pa_data(context, result); + return 0; + } + krb5_free_pa_data(context, result); + result = NULL; + if (retval == 0) { + fx_error_pa = krb5int_find_pa_data(context, fast_response->padata, KRB5_PADATA_FX_ERROR); + if (fx_error_pa == NULL) { + krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, "Expecting FX_ERROR pa-data inside FAST container"); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0) { + scratch.data = (char *) fx_error_pa->contents; + scratch.length = fx_error_pa->length; + retval = decode_krb5_error(&scratch, &fx_error); + } + /* + * krb5_pa_data and krb5_typed_data are safe to cast between: + * they have the same type fields in the same order. + * (krb5_preauthtype is a krb5_int32). If krb5_typed_data is + * ever changed then this will need to be a copy not a cast. + */ + if (retval == 0) + retval = encode_krb5_typed_data( (krb5_typed_data **) fast_response->padata, + &encoded_td); + if (retval == 0) { + fx_error->e_data = *encoded_td; + free(encoded_td); /*contents owned by fx_error*/ + encoded_td = NULL; + krb5_free_error(context, err_reply); + *err_replyptr = fx_error; + fx_error = NULL; + *out_padata = fast_response->padata; + fast_response->padata = NULL; + /* + * If there is more than the fx_error padata, then we want + * to retry the error if a cookie is present + */ + *retry = (*out_padata)[1] != NULL; + if (krb5int_find_pa_data(context, *out_padata, KRB5_PADATA_FX_COOKIE) == NULL) + *retry = 0; + } + if (fx_error) + krb5_free_error(context, fx_error); + krb5_free_fast_response(context, fast_response); + } else { /*not FAST*/ + *retry = (err_reply->e_data.length > 0); + if ((err_reply->error == KDC_ERR_PREAUTH_REQUIRED + ||err_reply->error == KDC_ERR_PREAUTH_FAILED) && err_reply->e_data.length) { + krb5_pa_data **result = NULL; + retval = decode_krb5_padata_sequence(&err_reply->e_data, &result); + if (retval == 0) + if (retval == 0) { + *out_padata = result; + + return 0; + } + krb5_free_pa_data(context, result); + krb5_set_error_message(context, retval, + "Error decoding padata in error reply"); + return retval; + } + } + return retval; +} + + +krb5_error_code krb5int_fast_process_response +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_rep *resp, + krb5_keyblock **strengthen_key) +{ + krb5_error_code retval = 0; + krb5_fast_response *fast_response = NULL; + krb5_data *encoded_ticket = NULL; + krb5_boolean cksum_valid; + krb5_clear_error_message(context); + *strengthen_key = NULL; + if (state->armor_key == 0) + return 0; + retval = decrypt_fast_reply(context, state, resp->padata, + &fast_response); + if (retval == 0) { + if (fast_response->finished == 0) { + retval = KRB5_KDCREP_MODIFIED; + krb5_set_error_message(context, retval, "FAST response missing finish message in KDC reply"); + } + } + if (retval == 0) + retval = encode_krb5_ticket(resp->ticket, &encoded_ticket); + if (retval == 0) + retval = krb5_c_verify_checksum(context, state->armor_key, + KRB5_KEYUSAGE_FAST_FINISHED, + encoded_ticket, + &fast_response->finished->ticket_checksum, + &cksum_valid); + if (retval == 0 && cksum_valid == 0) { + retval = KRB5_KDCREP_MODIFIED; + krb5_set_error_message(context, retval, "ticket modified in KDC reply"); + } + if (retval == 0) { + krb5_free_principal(context, resp->client); + resp->client = fast_response->finished->client; + fast_response->finished->client = NULL; + *strengthen_key = fast_response->strengthen_key; + fast_response->strengthen_key = NULL; + krb5_free_pa_data(context, resp->padata); + resp->padata = fast_response->padata; + fast_response->padata = NULL; + } + if (fast_response) + krb5_free_fast_response(context, fast_response); + if (encoded_ticket) + krb5_free_data(context, encoded_ticket); + return retval; +} + +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *out_key) +{ + krb5_keyblock *key = NULL; + krb5_error_code retval = 0; + krb5_free_keyblock_contents(context, out_key); + if (strengthen_key) { + retval = krb5_c_fx_cf2_simple(context, strengthen_key, + "strengthenkey", existing_key, "replykey", &key); + if (retval == 0) { + *out_key = *key; + free(key); + } + } else { + retval = krb5_copy_keyblock_contents(context, existing_key, out_key); + } + return retval; +} + + +krb5_error_code +krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state) +{ + krb5_error_code retval = 0; + struct krb5int_fast_request_state *local_state ; + local_state = malloc(sizeof *local_state); + if (local_state == NULL) + return ENOMEM; + memset(local_state, 0, sizeof(*local_state)); + *state = local_state; + return 0; +} + +void +krb5int_fast_free_state( krb5_context context, struct krb5int_fast_request_state *state) +{ + /*We are responsible for none of the store in the fast_outer_req*/ + krb5_free_keyblock(context, state->armor_key); + krb5_free_fast_armor(context, state->armor); + free(state); +} + +krb5_pa_data * krb5int_find_pa_data +(krb5_context context, krb5_pa_data *const *padata, krb5_preauthtype pa_type) +{ + krb5_pa_data * const *tmppa; + + if (padata == NULL) + return NULL; + + for (tmppa = padata; *tmppa != NULL; tmppa++) { + if ((*tmppa)->pa_type == pa_type) + break; + } + + return *tmppa; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/fast.h b/krb5-1-7/src/lib/krb5/krb/fast.h new file mode 100644 index 000000000..4cc142335 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/fast.h @@ -0,0 +1,82 @@ +/* + * lib/krb5/krb/fast.h + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 KRB_FAST_H + +#define KRB_FAST_H + +#include + +struct krb5int_fast_request_state { + krb5_kdc_req fast_outer_request; + krb5_keyblock *armor_key; /*non-null means fast is in use*/ + krb5_fast_armor *armor; + krb5_ui_4 fast_state_flags; + krb5_ui_4 fast_options; + krb5_int32 nonce; +}; + +krb5_error_code +krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_req *request, krb5_data **encoded_req_body); + +typedef krb5_error_code(*kdc_req_encoder_proc) (const krb5_kdc_req *, krb5_data **); + +krb5_error_code +krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + const krb5_data *to_be_checksummed, kdc_req_encoder_proc encoder, + krb5_data **encoded_request); +krb5_error_code +krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_state *state, + krb5_error **err_replyptr , krb5_pa_data ***out_padata, + krb5_boolean *retry); + +krb5_error_code krb5int_fast_process_response +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_kdc_rep *resp, + krb5_keyblock **strengthen_key); + +krb5_error_code +krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state); + +void +krb5int_fast_free_state( krb5_context , struct krb5int_fast_request_state *state); +krb5_error_code krb5int_fast_as_armor +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_gic_opt_ext *opte, + krb5_kdc_req *request); + +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *output_key); + + + +#endif diff --git a/krb5-1-7/src/lib/krb5/krb/free_rtree.c b/krb5-1-7/src/lib/krb5/krb/free_rtree.c new file mode 100644 index 000000000..90c9dd3c8 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/free_rtree.c @@ -0,0 +1,43 @@ +/* + * 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; + if (realms == NULL) + return; + while (*nrealms) { + krb5_free_principal(context, *nrealms); + nrealms++; + } + free(realms); +} diff --git a/krb5-1-7/src/lib/krb5/krb/fwd_tgt.c b/krb5-1-7/src/lib/krb5/krb/fwd_tgt.c new file mode 100644 index 000000000..ccaef4d88 --- /dev/null +++ b/krb5-1-7/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 +#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; + free(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-7/src/lib/krb5/krb/gc_frm_kdc.c b/krb5-1-7/src/lib/krb5/krb/gc_frm_kdc.c new file mode 100644 index 000000000..be1e7b463 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/gc_frm_kdc.c @@ -0,0 +1,1361 @@ +/* + * Copyright (c) 1994,2003,2005,2007 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 +#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; + krb5_creds *offpath_tgt; +}; + +/* + * 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) + +/* + * 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, int *tgtptr_isoffpath); +static krb5_error_code chase_offpath(struct tr_state *, krb5_principal, + krb5_principal); +static krb5_error_code offpath_loopchk(struct tr_state *ts, + krb5_creds *tgt, krb5_creds *reftgts[], unsigned int rcount); + +/* + * 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->ntgts > 0); + 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 && data_eq(*r1, *r2)) { + break; + } + } + if (*kdcptr != NULL) { + ts->nxt_kdc = kdcptr; + TR_DBG_RET(ts, "find_nxt_kdc", 0); + return 0; + } + + r2 = krb5_princ_component(ts->ctx, ts->kdc_list[0], 1); + if (r1 != NULL && r2 != NULL && + r1->length == r2->length && + !memcmp(r1->data, r2->data, r1->length)) { + TR_DBG_RET(ts, "find_nxt_kdc: looped back to local", + KRB5_KDCREP_MODIFIED); + return KRB5_KDCREP_MODIFIED; + } + + /* + * Realm is not in our list; we probably got an unexpected realm + * referral. + */ + ts->offpath_tgt = ts->nxt_tgt; + if (ts->cur_kdc == ts->kdc_list) { + /* + * Local KDC referred us off path; trust it for caching + * purposes. + */ + return 0; + } + /* + * Unlink the off-path TGT from KDC_TGTS but don't free it, + * because we should return it. + */ + ts->kdc_tgts[--ts->ntgts] = NULL; + ts->nxt_tgt = ts->cur_tgt; + 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; + } + /* + * In case of errors in try_kdc() or find_nxt_kdc(), continue + * looping through the KDC list. + */ + } + /* + * 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, + int *tgtptr_isoffpath) +{ + 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; + + if (ts->offpath_tgt != NULL) { + retval = chase_offpath(ts, client, server); + if (retval) + goto cleanup; + break; + } + assert(ts->cur_kdc != ts->nxt_kdc); + } + + if (NXT_TGT_IS_CACHED(ts)) { + assert(ts->offpath_tgt == NULL); + *out_cc_tgt = *ts->cur_cc_tgt; + *out_tgt = out_cc_tgt; + MARK_CUR_CC_TGT_CLEAN(ts); + } else if (ts->offpath_tgt != NULL){ + *out_tgt = ts->offpath_tgt; + } 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; + *tgtptr_isoffpath = (ts->offpath_tgt != NULL); + return retval; +} + +/* + * chase_offpath() + * + * Chase off-path TGT referrals. + * + * If we are traversing a trusted path (either hierarchically derived + * or explicit capath) and get a TGT pointing to a realm off this + * path, query the realm referenced by that off-path TGT. Repeat + * until we get to the destination realm or encounter an error. + * + * CUR_TGT is always either pointing into REFTGTS or is an alias for + * TS->OFFPATH_TGT. + */ +static krb5_error_code +chase_offpath(struct tr_state *ts, + krb5_principal client, krb5_principal server) +{ + krb5_error_code retval; + krb5_creds mcred; + krb5_creds *cur_tgt, *nxt_tgt, *reftgts[KRB5_REFERRAL_MAXHOPS]; + krb5_data *rsrc, *rdst, *r1; + unsigned int rcount, i; + + rdst = krb5_princ_realm(ts->ctx, server); + cur_tgt = ts->offpath_tgt; + + for (rcount = 0; rcount < KRB5_REFERRAL_MAXHOPS; rcount++) { + nxt_tgt = NULL; + memset(&mcred, 0, sizeof(mcred)); + rsrc = krb5_princ_component(ts->ctx, cur_tgt->server, 1); + retval = krb5_tgtname(ts->ctx, rdst, rsrc, &mcred.server); + if (retval) + goto cleanup; + mcred.client = client; + retval = krb5_get_cred_via_tkt(ts->ctx, cur_tgt, + FLAGS2OPTS(cur_tgt->ticket_flags), + cur_tgt->addresses, &mcred, &nxt_tgt); + mcred.client = NULL; + krb5_free_principal(ts->ctx, mcred.server); + mcred.server = NULL; + if (retval) + goto cleanup; + if (!IS_TGS_PRINC(ts->ctx, nxt_tgt->server)) { + retval = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + r1 = krb5_princ_component(ts->ctx, nxt_tgt->server, 1); + if (rdst->length == r1->length && + !memcmp(rdst->data, r1->data, rdst->length)) { + retval = 0; + goto cleanup; + } + retval = offpath_loopchk(ts, nxt_tgt, reftgts, rcount); + if (retval) + goto cleanup; + reftgts[rcount] = nxt_tgt; + cur_tgt = nxt_tgt; + nxt_tgt = NULL; + } + /* Max hop count exceeded. */ + retval = KRB5_KDCREP_MODIFIED; + +cleanup: + if (mcred.server != NULL) { + krb5_free_principal(ts->ctx, mcred.server); + } + /* + * Don't free TS->OFFPATH_TGT if it's in the list of cacheable + * TGTs to be returned by do_traversal(). + */ + if (ts->offpath_tgt != ts->nxt_tgt) { + krb5_free_creds(ts->ctx, ts->offpath_tgt); + } + ts->offpath_tgt = NULL; + if (nxt_tgt != NULL) { + if (retval) + krb5_free_creds(ts->ctx, nxt_tgt); + else + ts->offpath_tgt = nxt_tgt; + } + for (i = 0; i < rcount; i++) { + krb5_free_creds(ts->ctx, reftgts[i]); + } + return retval; +} + +/* + * offpath_loopchk() + * + * Check for loop back to previously-visited realms, both off-path and + * on-path. + */ +static krb5_error_code +offpath_loopchk(struct tr_state *ts, + krb5_creds *tgt, krb5_creds *reftgts[], unsigned int rcount) +{ + krb5_data *r1, *r2; + unsigned int i; + + r1 = krb5_princ_component(ts->ctx, tgt->server, 1); + for (i = 0; i < rcount; i++) { + r2 = krb5_princ_component(ts->ctx, reftgts[i]->server, 1); + if (r1->length == r2->length && + !memcmp(r1->data, r2->data, r1->length)) + return KRB5_KDCREP_MODIFIED; + } + for (i = 0; i < ts->ntgts; i++) { + r2 = krb5_princ_component(ts->ctx, ts->kdc_tgts[i]->server, 1); + if (r1->length == r2->length && + !memcmp(r1->data, r2->data, r1->length)) + return KRB5_KDCREP_MODIFIED; + } + return 0; +} + +/* + * 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. + */ + +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_creds *otgtptr = NULL; + int tgtptr_isoffpath = 0; + krb5_boolean old_use_conf_ktypes; + char **hrealms; + unsigned 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")); + tgtptr_isoffpath = 0; + otgtptr = NULL; + retval = do_traversal(context, ccache, client, server, + &cc_tgt, &tgtptr, tgts, &tgtptr_isoffpath); + } + 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. + */ + + /* + * Save TGTPTR because we rewrite it in the referral loop, and + * we might need to explicitly free it later. + */ + otgtptr = tgtptr; + 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 (data_eq(*r1, *r2)) { + 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;iserver); + 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; + *out_cred = NULL; + /* 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 / 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); + tgtptr = NULL; + /* Free saved TGT in OTGTPTR if it was off-path. */ + if (tgtptr_isoffpath) + krb5_free_creds(context, otgtptr); + otgtptr = NULL; + /* 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)) { + tgtptr_isoffpath = 0; + retval = do_traversal(context, ccache, client, server, + &cc_tgt, &tgtptr, tgts, &tgtptr_isoffpath); + } + if (retval) + goto cleanup; + otgtptr = tgtptr; + + /* + * 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); + if (tgtptr_isoffpath) + krb5_free_creds(context, otgtptr); + 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;iclient, + &(*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_keyblock; + (*ppcreds)->second_ticket = *pdata; + free(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_contents(context, &(*ppcreds)->keyblock); + +cleanup: + free (*ppcreds); + *ppcreds = NULL; + 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) && + data_eq(*in_cred->server->data[1], *in_cred->client->realm) { + /* Attempted to rewrite local TGS. */ + return KRB5_KDCREP_MODIFIED; + } +#endif + return 0; +} + +/* Return true if a TGS credential is for the client's local realm. */ +static inline int +tgt_is_local_realm(krb5_creds *tgt) +{ + return (tgt->server->length == 2 + && data_eq_string(tgt->server->data[0], KRB5_TGS_NAME) + && data_eq(tgt->server->data[1], tgt->client->realm) + && data_eq(tgt->server->realm, tgt->client->realm)); +} + +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; + krb5_keyblock *subkey = NULL; + +#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 = krb5int_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, &subkey); + 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.length, + err_reply->text.data); + break; + case KDC_ERR_S_PRINCIPAL_UNKNOWN: + { + char *s_name; + if (krb5_unparse_name(context, in_cred->server, &s_name) == 0) { + krb5_set_error_message(context, retval, + "Server %s not found in Kerberos database", + s_name); + krb5_free_unparsed_name(context, s_name); + } else + /* In case there's a stale S_PRINCIPAL_UNKNOWN + report already noted. */ + krb5_clear_error_message(context); + } + 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; + } + + /* Unfortunately, Heimdal at least up through 1.2 encrypts using + the session key not the subsession key. So we try both. */ + if ((retval = krb5int_decode_tgs_rep(context, &tgsrep.response, + subkey, + KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY, &dec_rep))) { + if ((krb5int_decode_tgs_rep(context, &tgsrep.response, + &tkt->keyblock, + KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY, &dec_rep)) == 0) + retval = 0; + else goto error_4; + } + + if (dec_rep->msg_type != KRB5_TGS_REP) { + retval = KRB5KRB_AP_ERR_MSG_TYPE; + goto error_3; + } + + /* + * Don't trust the ok-as-delegate flag from foreign KDCs unless the + * cross-realm TGT also had the ok-as-delegate flag set. + */ + if (!tgt_is_local_realm(tkt) + && !(tkt->ticket_flags & TKT_FLG_OK_AS_DELEGATE)) + dec_rep->enc_part2->flags &= ~TKT_FLG_OK_AS_DELEGATE; + + /* 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:; + if (subkey != NULL) + krb5_free_keyblock(context, subkey); + + 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-7/src/lib/krb5/krb/gen_seqnum.c b/krb5-1-7/src/lib/krb5/krb/gen_seqnum.c new file mode 100644 index 000000000..06564ee4a --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/gen_seqnum.c @@ -0,0 +1,76 @@ +/* + * 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 + +static inline krb5_data +key2data (krb5_keyblock k) +{ + krb5_data d; + d.magic = KV5M_DATA; + d.length = k.length; + d.data = (char *) k.contents; + return d; +} + +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 = key2data(*key); + 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-7/src/lib/krb5/krb/gen_subkey.c b/krb5-1-7/src/lib/krb5/krb/gen_subkey.c new file mode 100644 index 000000000..601ab739a --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/gen_subkey.c @@ -0,0 +1,70 @@ +/* + * 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" + +static inline krb5_data +key2data (krb5_keyblock k) +{ + krb5_data d; + d.magic = KV5M_DATA; + d.length = k.length; + d.data = (char *) k.contents; + return d; +} + +krb5_error_code +krb5_generate_subkey_extended(krb5_context context, + const krb5_keyblock *key, + krb5_enctype enctype, + krb5_keyblock **subkey) +{ + krb5_error_code retval; + krb5_data seed; + + seed = key2data(*key); + 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, enctype, *subkey))) { + free(*subkey); + return(retval); + } + + return(0); +} + +krb5_error_code +krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblock **subkey) +{ + return krb5_generate_subkey_extended(context, key, key->enctype, subkey); +} diff --git a/krb5-1-7/src/lib/krb5/krb/get_creds.c b/krb5-1-7/src/lib/krb5/krb/get_creds.c new file mode 100644 index 000000000..fff8b903b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/get_creds.c @@ -0,0 +1,339 @@ +/* + * lib/krb5/krb/get_creds.c + * + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#include "int-proto.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; + int kdcopt = 0; + + 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))) { + free(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; + + if (options & KRB5_GC_CANONICALIZE) + kdcopt |= KDC_OPT_CANONICALIZE; + + retval = krb5_get_cred_from_kdc_opt(context, ccache, ncreds, + out_creds, &tgts, kdcopt); + 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; + } + /* + * Callers to krb5_get_cred_blah... must free up tgts even in + * error cases. + */ + if (tgts) krb5_free_tgt_creds(context, tgts); + if (retval) return retval; + + 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; + free(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-7/src/lib/krb5/krb/get_in_tkt.c b/krb5-1-7/src/lib/krb5/krb/get_in_tkt.c new file mode 100644 index 000000000..094814524 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/get_in_tkt.c @@ -0,0 +1,1558 @@ +/* + * lib/krb5/krb/get_in_tkt.c + * + * Copyright 1990,1991, 2003, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" +#include "fast.h" + +#if APPLE_PKINIT +#define IN_TKT_DEBUG 0 +#if IN_TKT_DEBUG +#define inTktDebug(args...) printf(args) +#else +#define inTktDebug(args...) +#endif +#endif /* APPLE_PKINIT */ + +/* + 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, + 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; +} + +#if APPLE_PKINIT +/* + * Common code to generate krb5_kdc_req.nonce. Like the original MIT code this + * just uses krb5_timeofday(); it should use a PRNG. Even more unfortunately this + * value is used interchangeably with an explicit now_time throughout this module... + */ +static krb5_error_code +gen_nonce(krb5_context context, + krb5_int32 *nonce) +{ + krb5_int32 time_now; + krb5_error_code retval = krb5_timeofday(context, &time_now); + if(retval) { + return retval; + } + *nonce = time_now; + return 0; +} +#endif /* APPLE_PKINIT */ + +/* + * 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_data *packet, const krb5_data *realm, + 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 reply; + char k4_version; /* same type as *(krb5_data::data) */ + int tcp_only = 0; + + reply.data = 0; + + /* set the nonce if the caller expects us to do it */ + + k4_version = packet->data[0]; +send_again: + retval = krb5_sendto_kdc(context, packet, + realm, + &reply, use_master, tcp_only); +#if APPLE_PKINIT + inTktDebug("krb5_sendto_kdc returned %d\n", (int)retval); +#endif /* APPLE_PKINIT */ + + 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 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 (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 { + /* + * Use salt corresponding to the client principal supplied by + * the KDC, which may differ from the requested principal if + * canonicalization is in effect. We will check + * as_reply->client later in verify_as_reply. + */ + if ((retval = krb5_principal2salt(context, as_reply->client, &salt))) + return(retval); + + retval = (*key_proc)(context, as_reply->enc_part.enctype, + &salt, keyseed, &decrypt_key); + free(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; + int canon_req; + int canon_ok; + + /* check the contents for sanity: */ + if (!as_reply->enc_part2->times.starttime) + as_reply->enc_part2->times.starttime = + as_reply->enc_part2->times.authtime; + + /* + * We only allow the AS-REP server name to be changed if the + * caller set the canonicalize flag (or requested an enterprise + * principal) and we requested (and received) a TGT. + */ + canon_req = ((request->kdc_options & KDC_OPT_CANONICALIZE) != 0) || + (krb5_princ_type(context, request->client) == KRB5_NT_ENTERPRISE_PRINCIPAL); + if (canon_req) { + canon_ok = IS_TGS_PRINC(context, request->server) && + IS_TGS_PRINC(context, as_reply->enc_part2->server); + } else + canon_ok = 0; + + if ((!canon_ok && + (!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->enc_part2->server, as_reply->ticket->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)) + ) { +#if APPLE_PKINIT + inTktDebug("verify_as_reply: KDCREP_MODIFIED\n"); + #if IN_TKT_DEBUG + if(request->client->realm.length && request->client->data->length) + inTktDebug("request: name %s realm %s\n", + request->client->realm.data, request->client->data->data); + if(as_reply->client->realm.length && as_reply->client->data->length) + inTktDebug("reply : name %s realm %s\n", + as_reply->client->realm.data, as_reply->client->data->data); + #endif +#endif /* APPLE_PKINIT */ + return KRB5_KDCREP_MODIFIED; + } + + if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) { + retval = krb5_set_real_time(context, + as_reply->enc_part2->times.authtime, -1); + 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; + free(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); + free(creds->keyblock.contents); + creds->keyblock.contents = 0; + creds->keyblock.length = 0; + } + if (creds->ticket.data) { + free(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=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, + 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_data *encoded_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 canon_flag; + int use_master = 0; + int referral_count = 0; + krb5_principal_data referred_client; + +#if APPLE_PKINIT + inTktDebug("krb5_get_in_tkt top\n"); +#endif /* APPLE_PKINIT */ + + if (! krb5_realm_compare(context, creds->client, creds->server)) + return KRB5_IN_TKT_REALM_MISMATCH; + + if (ret_as_reply) + *ret_as_reply = 0; + + referred_client = *(creds->client); + referred_client.realm.data = NULL; + referred_client.realm.length = 0; + + /* per referrals draft, enterprise principals imply canonicalization */ + canon_flag = ((options & KDC_OPT_CANONICALIZE) != 0) || + creds->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL; + + /* + * 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; +#if APPLE_PKINIT + retval = gen_nonce(context, (krb5_int32 *)&time_now); + if(retval) { + goto cleanup; + } + request.nonce = time_now; +#endif /* APPLE_PKINIT */ + + 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 APPLE_PKINIT + inTktDebug("krb5_get_in_tkt calling krb5_obtain_padata\n"); +#endif /* APPLE_PKINIT */ + 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 = encode_krb5_as_req(&request, &encoded_request)) != 0) + goto cleanup; + retval = send_as_request(context, encoded_request, + krb5_princ_realm(context, request.client), &err_reply, + &as_reply, &use_master); + krb5_free_data(context, encoded_request); + if (retval != 0) + 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 if (canon_flag && err_reply->error == KDC_ERR_WRONG_REALM) { + if (++referral_count > KRB5_REFERRAL_MAXHOPS || + err_reply->client == NULL || + err_reply->client->realm.length == 0) { + retval = KRB5KDC_ERR_WRONG_REALM; + krb5_free_error(context, err_reply); + goto cleanup; + } + /* Rewrite request.client with realm from error reply */ + if (referred_client.realm.data) { + krb5_free_data_contents(context, &referred_client.realm); + referred_client.realm.data = NULL; + } + retval = krb5int_copy_data_contents(context, + &err_reply->client->realm, + &referred_client.realm); + krb5_free_error(context, err_reply); + if (retval) + goto cleanup; + request.client = &referred_client; + 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); + } + if (referred_client.realm.data) + krb5_free_data_contents(context, &referred_client.realm); + 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] = KRB5_CONF_LIBDEFAULTS; + + /* + * Try number one: + * + * [libdefaults] + * REALM = { + * option = + * } + */ + + 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 = + */ + + 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 = strdup(nameval[0]); + if (!*ret_value) + retval = ENOMEM; + } + + 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, KRB5_CONF_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, encrypting_key; + krb5_keyblock *strengthen_key = NULL; + 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; + int canon_flag = 0; + krb5_principal_data referred_client; + krb5_boolean retry = 0; + struct krb5int_fast_request_state *fast_state = NULL; + krb5_pa_data **out_padata = NULL; + + + /* 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; + encrypting_key.length = 0; + encrypting_key.contents = NULL; + salt.length = 0; + salt.data = NULL; + + local_as_reply = 0; +#if APPLE_PKINIT + inTktDebug("krb5_get_init_creds top\n"); +#endif /* APPLE_PKINIT */ + + err_reply = NULL; + + /* referred_client is used to rewrite the client realm for referrals */ + referred_client = *client; + referred_client.realm.data = NULL; + referred_client.realm.length = 0; + ret = krb5int_fast_make_state(context, &fast_state); + if (ret) + goto cleanup; + + /* + * 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, + KRB5_CONF_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, + KRB5_CONF_PROXIABLE, &tempint)) == 0) + ; + else + tempint = 0; + if (tempint) + request.kdc_options |= KDC_OPT_PROXIABLE; + + /* canonicalize */ + if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_CANONICALIZE)) + tempint = 1; + else if ((ret = krb5_libdefault_boolean(context, &client->realm, + KRB5_CONF_CANONICALIZE, &tempint)) == 0) + ; + else + tempint = 0; + if (tempint) + request.kdc_options |= KDC_OPT_CANONICALIZE; + + /* 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, + KRB5_CONF_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, + KRB5_CONF_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; + + /* per referrals draft, enterprise principals imply canonicalization */ + canon_flag = ((request.kdc_options & KDC_OPT_CANONICALIZE) != 0) || + client->type == KRB5_NT_ENTERPRISE_PRINCIPAL; + + /* 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) { + char *p = realloc(request.server->realm.data, + request.client->realm.length); + if (p == NULL) { + ret = ENOMEM; + goto cleanup; + } + request.server->realm.data = p; + } + + 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); + + + 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, + KRB5_CONF_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 + */ + { + unsigned char random_buf[4]; + krb5_data random_data; + + random_data.length = 4; + random_data.data = (char *)random_buf; + if (krb5_c_random_make_octets(context, &random_data) == 0) + /* See RT ticket 3196 at MIT. If we set the high bit, we + may have compatibility problems with Heimdal, because + we (incorrectly) encode this value as signed. */ + request.nonce = 0x7fffffff & load_32_n(random_buf); + else + /* XXX Yuck. Old version. */ + request.nonce = (krb5_int32) time_now; + } + ret = krb5int_fast_as_armor(context, fast_state, options, &request); + if (ret != 0) + goto cleanup; + /* give the preauth plugins a chance to prep the request body */ + krb5_preauth_prepare_request(context, options, &request); + ret = krb5int_fast_prep_req_body(context, fast_state, + &request, &encoded_request_body); + if (ret) + goto cleanup; + + get_data_rock.magic = CLIENT_ROCK_MAGIC; + get_data_rock.etype = &etype; + get_data_rock.fast_state = fast_state; + + /* 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; + if (out_padata) { + krb5_free_pa_data(context, out_padata); + out_padata = NULL; + } + } 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 = krb5int_fast_prep_req(context, fast_state, + &request, encoded_request_body, + encode_krb5_as_req, &encoded_previous_request); + if (ret) + goto cleanup; + + err_reply = 0; + local_as_reply = 0; + if ((ret = send_as_request(context, encoded_previous_request, + krb5_princ_realm(context, request.client), &err_reply, + &local_as_reply, use_master))) + goto cleanup; + + if (err_reply) { + ret = krb5int_fast_process_error(context, fast_state, &err_reply, + &out_padata, &retry); + if (ret !=0) + goto cleanup; + if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED && retry) { + /* reset the list of preauth types to try */ + if (preauth_to_use) { + krb5_free_pa_data(context, preauth_to_use); + preauth_to_use = NULL; + } + preauth_to_use = out_padata; + out_padata = NULL; + krb5_free_error(context, err_reply); + err_reply = NULL; + ret = sort_krb5_padata_sequence(context, + &request.server->realm, + preauth_to_use); + if (ret) + goto cleanup; + /* continue to next iteration */ + } else if (canon_flag && err_reply->error == KDC_ERR_WRONG_REALM) { + if (err_reply->client == NULL || + err_reply->client->realm.length == 0) { + ret = KRB5KDC_ERR_WRONG_REALM; + krb5_free_error(context, err_reply); + goto cleanup; + } + /* Rewrite request.client with realm from error reply */ + if (referred_client.realm.data) { + krb5_free_data_contents(context, &referred_client.realm); + referred_client.realm.data = NULL; + } + ret = krb5int_copy_data_contents(context, + &err_reply->client->realm, + &referred_client.realm); + krb5_free_error(context, err_reply); + err_reply = NULL; + if (ret) + goto cleanup; + request.client = &referred_client; + } else { + if (retry) { + /* 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 APPLE_PKINIT + inTktDebug("krb5_get_init_creds done with send_as_request loop lc %d\n", + (int)loopcount); +#endif /* APPLE_PKINIT */ + 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); + ret = krb5int_fast_process_response(context, fast_state, + local_as_reply, &strengthen_key); + if (ret) + goto cleanup; + if ((ret = sort_krb5_padata_sequence(context, &request.server->realm, + local_as_reply->padata))) + goto cleanup; + etype = local_as_reply->enc_part.enctype; + 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))) { +#if APPLE_PKINIT + inTktDebug("krb5_get_init_creds krb5_do_preauth returned %d\n", (int)ret); +#endif /* APPLE_PKINIT */ + goto cleanup; + } + + /* + * If we haven't gotten a salt from another source yet, set up one + * corresponding to the client principal returned by the KDC. We + * could get the same effect by passing local_as_reply->client to + * gak_fct below, but that would put the canonicalized client name + * in the prompt, which raises issues of needing to sanitize + * unprintable characters. So for now we just let it affect the + * salt. local_as_reply->client will be checked later on in + * verify_as_reply. + */ + if (salt.length == SALT_TYPE_AFS_LENGTH && salt.data == NULL) { + ret = krb5_principal2salt(context, local_as_reply->client, &salt); + if (ret) + 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 = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; + ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, + NULL, &encrypting_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; + + ret = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; + if ((ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, + NULL, &encrypting_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: + if (ret != 0) { + char *client_name; + /* See if we can produce a more detailed error message. */ + switch (ret) { + case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: + client_name = NULL; + if (krb5_unparse_name(context, client, &client_name) == 0) { + krb5_set_error_message(context, ret, + "Client '%s' not found in Kerberos database", + client_name); + free(client_name); + } + break; + default: + break; + } + } + krb5_preauth_request_context_fini(context); + krb5_free_keyblock(context, strengthen_key); + if (encrypting_key.contents) + krb5_free_keyblock_contents(context, &encrypting_key); + if (fast_state) + krb5int_fast_free_state(context, fast_state); + if (out_padata) + krb5_free_pa_data(context, out_padata); + 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)))) + free(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); + if (referred_client.realm.data) + krb5_free_data_contents(context, &referred_client.realm); + + return(ret); +} diff --git a/krb5-1-7/src/lib/krb5/krb/gic_keytab.c b/krb5-1-7/src/lib/krb5/krb/gic_keytab.c new file mode 100644 index 000000000..923579487 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/gic_keytab.c @@ -0,0 +1,222 @@ +/* + * lib/krb5/krb/gic_keytab.c + * + * Copyright (C) 2002, 2003, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 LEAN_CLIENT + +#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; + free(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; +} + +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/krb/gic_opt.c b/krb5-1-7/src/lib/krb5/krb/gic_opt.c new file mode 100644 index 000000000..72203f0e7 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/gic_opt.c @@ -0,0 +1,487 @@ +#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_canonicalize(krb5_get_init_creds_opt *opt, int canonicalize) +{ + if (canonicalize) + opt->flags |= KRB5_GET_INIT_CREDS_OPT_CANONICALIZE; + else + opt->flags &= ~(KRB5_GET_INIT_CREDS_OPT_CANONICALIZE); +} + +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); + if (opte->opt_private->fast_ccache_name) + free(opte->opt_private->fast_ccache_name); + 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) { + oe->flags = opt->flags; + oe->tkt_life = opt->tkt_life; + oe->renew_life = opt->renew_life; + oe->forwardable = opt->forwardable; + oe->proxiable = opt->proxiable; + oe->etype_list = opt->etype_list; + oe->etype_list_length = opt->etype_list_length; + oe->address_list = opt->address_list; + oe->preauth_list = opt->preauth_list; + oe->preauth_list_length = opt->preauth_list_length; + oe->salt = opt->salt; + } + + /* + * 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; + opte->opt_private->preauth_data = newpad; + + 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; + 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); +} +krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache_name +(krb5_context context, krb5_get_init_creds_opt *opt, const char *ccache_name) +{ + krb5_error_code retval = 0; + krb5_gic_opt_ext *opte; + + retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0, + "krb5_get_init_creds_opt_set_fast_ccache_name"); + if (retval) + return retval; + if (opte->opt_private->fast_ccache_name) { + free(opte->opt_private->fast_ccache_name); + } + opte->opt_private->fast_ccache_name = strdup(ccache_name); + if (opte->opt_private->fast_ccache_name == NULL) + retval = ENOMEM; + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/gic_pwd.c b/krb5-1-7/src/lib/krb5/krb/gic_pwd.c new file mode 100644 index 000000000..5079e056e --- /dev/null +++ b/krb5-1-7/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); + + snprintf(promptstr, sizeof(promptstr), "Password for %s", clientstr); + 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) + free(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 (strlcpy(pw0.data, password, sizeof(pw0array)) >= sizeof(pw0array)) { + ret = EINVAL; + goto cleanup; + } + pw0.length = strlen(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, fail */ + + if ((ret == KRB5_KDC_UNREACH) || + (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_KIM + 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; + + strlcpy(banner, "Password expired. You must change it now.", + sizeof(banner)); + + 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; + snprintf(banner, sizeof(banner), + "%s. Please try again.", error_message(ret)); + } else if (pw0.length == 0) { + ret = KRB5_CHPW_PWDNULL; + snprintf(banner, sizeof(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) { + free(result_string.data); + break; + } + + /* set this in case the retry loop falls through */ + + ret = KRB5_CHPW_FAIL; + + if (result_code != KRB5_KPASSWD_SOFTERROR) { + free(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; + + snprintf(banner, sizeof(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 : ""); + + free(code_string.data); + free(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) + snprintf(banner, sizeof(banner), + "Warning: Your password will expire in less than one hour."); + else if (hours <= 48) + snprintf(banner, sizeof(banner), + "Warning: Your password will expire in %d hour%s.", + hours, (hours == 1)?"":"s"); + else + snprintf(banner, sizeof(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) + snprintf(banner, sizeof(banner), + "Warning: Your password will expire in less than one hour on %s", + ts); + else if (delta < 86400*2) + snprintf(banner, sizeof(banner), + "Warning: Your password will expire in %d hour%s on %s", + delta / 3600, delta < 7200 ? "" : "s", ts); + else + snprintf(banner, sizeof(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-7/src/lib/krb5/krb/in_tkt_sky.c b/krb5-1-7/src/lib/krb5/krb/in_tkt_sky.c new file mode 100644 index 000000000..d98411fd7 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/in_tkt_sky.c @@ -0,0 +1,107 @@ +/* + * lib/krb5/krb/in_tkt_sky.c + * + * Copyright 1990,1991, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 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); +#ifndef LEAN_CLIENT + else + return krb5_get_in_tkt_with_keytab(context, options, addrs, ktypes, + pre_auth_types, NULL, ccache, + creds, ret_as_reply); +#endif /* LEAN_CLIENT */ +} diff --git a/krb5-1-7/src/lib/krb5/krb/init_ctx.c b/krb5-1-7/src/lib/krb5/krb/init_ctx.c new file mode 100644 index 000000000..67dad8cb2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/init_ctx.c @@ -0,0 +1,617 @@ +/* + * lib/krb5/krb/init_ctx.c + * + * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#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 = calloc(1, sizeof(struct _krb5_context)); + if (!ctx) + return ENOMEM; + 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; + + retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_ALLOW_WEAK_CRYPTO, NULL, 1, &tmp); + if (retval) + goto cleanup; + ctx->allow_weak_crypto = tmp; + + /* 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, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CLOCKSKEW, + 0, 5 * 60, &tmp); + ctx->clockskew = tmp; + +#if 0 + /* Default ticket lifetime is currently not supported */ + profile_get_integer(ctx->profile, KRB5_CONF_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, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, 0, CKSUMTYPE_RSA_MD5, + &tmp); + ctx->kdc_req_sumtype = tmp; + + profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_AP_REQ_CHECKSUM_TYPE, 0, 0, + &tmp); + ctx->default_ap_req_sumtype = tmp; + + profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_SAFE_CHECKSUM_TYPE, 0, + CKSUMTYPE_RSA_MD5_DES, &tmp); + ctx->default_safe_sumtype = tmp; + + profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_KDC_DEFAULT_OPTIONS, 0, + KDC_OPT_RENEWABLE_OK, &tmp); + ctx->kdc_default_options = tmp; +#define DEFAULT_KDC_TIMESYNC 1 + profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_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, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CCACHE_TYPE, + 0, DEFAULT_CCACHE_TYPE, &tmp); + ctx->fcc_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) +{ + if (ctx == NULL) + return; + krb5_os_free_context(ctx); + + free(ctx->in_tkt_ktypes); + ctx->in_tkt_ktypes = 0; + free(ctx->tgs_ktypes); + ctx->tgs_ktypes = 0; + 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; + if (!context->allow_weak_crypto && krb5_c_weak_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; + krb5_enctype ktype; + + 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 = NULL; + char *sp = NULL, *ep = NULL; + int i, j, count; + krb5_error_code code; + + code = profile_get_string(context->profile, KRB5_CONF_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) { + profile_release_string(retval); + return ENOMEM; + } + + sp = retval; + j = 0; + i = 1; + while (1) { + if (!krb5_string_to_enctype(sp, &ktype) && + (context->allow_weak_crypto || !krb5_c_weak_enctype(ktype))) { + old_ktypes[j] = ktype; + 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, KRB5_CONF_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; + if (!context->allow_weak_crypto && krb5_c_weak_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, KRB5_CONF_DEFAULT_TKT_ENCTYPES, + 0, NULL)); + else + return(get_profile_etype_list(context, ktypes, KRB5_CONF_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, KRB5_CONF_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); +} + +/* The same as krb5_is_permitted_enctype, but verifies multiple etype's + * Returns 0 is either the list of the permitted enc types is not available + * or all requested etypes are not permitted. Otherwise returns 1. + */ + +krb5_boolean +krb5_is_permitted_enctype_ext ( krb5_context context, + krb5_etypes_permitted *etypes) +{ + krb5_enctype *list, *ptr; + krb5_boolean ret = 0; + int i = 0; + + if (krb5_get_permitted_enctypes(context, &list)) + return(0); + + for ( i=0; i< etypes->etype_count; i++ ) + { + for (ptr = list; *ptr; ptr++) + { + if (*ptr == etypes->etype[i]) + { + etypes->etype_ok[i] = TRUE; + 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->dal_handle = 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-7/src/lib/krb5/krb/init_keyblock.c b/krb5-1-7/src/lib/krb5/krb/init_keyblock.c new file mode 100644 index 000000000..3be842ac8 --- /dev/null +++ b/krb5-1-7/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 + +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-7/src/lib/krb5/krb/int-proto.h b/krb5-1-7/src/lib/krb5/krb/int-proto.h new file mode 100644 index 000000000..b81fe2566 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/int-proto.h @@ -0,0 +1,69 @@ +/* + * 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); + +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); + +#define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew) + +#define IS_TGS_PRINC(c, p) \ + (krb5_princ_size((c), (p)) == 2 && \ + data_eq_string(*krb5_princ_component((c), (p), 0), KRB5_TGS_NAME)) + +#endif /* KRB5_INT_FUNC_PROTO__ */ + diff --git a/krb5-1-7/src/lib/krb5/krb/kdc_rep_dc.c b/krb5-1-7/src/lib/krb5/krb/kdc_rep_dc.c new file mode 100644 index 000000000..42559b2f1 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/kerrs.c b/krb5-1-7/src/lib/krb5/krb/kerrs.c new file mode 100644 index 000000000..51f1eca97 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/kerrs.c @@ -0,0 +1,149 @@ +/* + * 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 +#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 + +#undef krb5_set_error_message +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_C +krb5_set_error_message_fl (krb5_context ctx, krb5_error_code code, + const char *file, int line, 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_fl (&ctx->err, code, file, line, 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 +} + +/* Set the error message state of dest_ctx to that of src_ctx. */ +void KRB5_CALLCONV +krb5_copy_error_message (krb5_context dest_ctx, krb5_context src_ctx) +{ + if (dest_ctx == src_ctx) + return; + if (src_ctx->err.msg) { + krb5int_set_error(&dest_ctx->err, src_ctx->err.code, "%s", + src_ctx->err.msg); + } else { + krb5int_clear_error(&dest_ctx->err); + } +} + +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-7/src/lib/krb5/krb/kfree.c b/krb5-1-7/src/lib/krb5/krb/kfree.c new file mode 100644 index 000000000..402063cb6 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/kfree.c @@ -0,0 +1,861 @@ +/* + * lib/krb5/free/f_addr.c + * + * Copyright 1990-1998, 2009 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() + */ +/* + * Copyright (c) 2006-2008, 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" +#include + +void KRB5_CALLCONV +krb5_free_address(krb5_context context, krb5_address *val) +{ + if (val == NULL) + return; + free(val->contents); + free(val); +} + +void KRB5_CALLCONV +krb5_free_addresses(krb5_context context, krb5_address **val) +{ + register krb5_address **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(val); +} + + +void KRB5_CALLCONV +krb5_free_alt_method(krb5_context context, + krb5_alt_method *alt) +{ + if (alt) { + free(alt->data); + free(alt); + } +} +void KRB5_CALLCONV +krb5_free_ap_rep(krb5_context context, register krb5_ap_rep *val) +{ + if (val == NULL) + return; + free(val->enc_part.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_ap_req(krb5_context context, register krb5_ap_req *val) +{ + if (val == NULL) + return; + krb5_free_ticket(context, val->ticket); + free(val->authenticator.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val) +{ + if (val == NULL) + return; + krb5_free_keyblock(context, val->subkey); + free(val); +} + +void KRB5_CALLCONV +krb5_free_authenticator_contents(krb5_context context, krb5_authenticator *val) +{ + if (val == NULL) + return; + krb5_free_checksum(context, val->checksum); + val->checksum = 0; + krb5_free_principal(context, val->client); + val->client = 0; + krb5_free_keyblock(context, val->subkey); + val->subkey = 0; + 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; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(val); +} + +void KRB5_CALLCONV +krb5_free_authenticator(krb5_context context, krb5_authenticator *val) +{ + if (val == NULL) + return; + krb5_free_authenticator_contents(context, val); + free(val); +} + +void KRB5_CALLCONV +krb5_free_checksum(krb5_context context, register krb5_checksum *val) +{ + if (val == NULL) + return; + krb5_free_checksum_contents(context, val); + free(val); +} + +void KRB5_CALLCONV +krb5_free_checksum_contents(krb5_context context, register krb5_checksum *val) +{ + if (val == NULL) + return; + free(val->contents); + val->contents = 0; +} + +void KRB5_CALLCONV +krb5_free_cred(krb5_context context, register krb5_cred *val) +{ + if (val == NULL) + return; + krb5_free_tickets(context, val->tickets); + free(val->enc_part.ciphertext.data); + free(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 == NULL) + return; + krb5_free_principal(context, val->client); + val->client = 0; + krb5_free_principal(context, val->server); + val->server = 0; + krb5_free_keyblock_contents(context, &val->keyblock); + free(val->ticket.data); + val->ticket.data = 0; + free(val->second_ticket.data); + val->second_ticket.data = 0; + krb5_free_addresses(context, val->addresses); + val->addresses = 0; + 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 == NULL) + return; + krb5_free_address(context, val->r_address); + val->r_address = 0; + krb5_free_address(context, val->s_address); + val->s_address = 0; + + if (val->ticket_info) { + for (temp = val->ticket_info; *temp; temp++) { + krb5_free_keyblock(context, (*temp)->session); + krb5_free_principal(context, (*temp)->client); + krb5_free_principal(context, (*temp)->server); + krb5_free_addresses(context, (*temp)->caddrs); + free(*temp); + } + free(val->ticket_info); + val->ticket_info = 0; + } +} + + +void KRB5_CALLCONV +krb5_free_creds(krb5_context context, krb5_creds *val) +{ + if (val == NULL) + return; + krb5_free_cred_contents(context, val); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_data(krb5_context context, krb5_data *val) +{ + if (val == NULL) + return; + free(val->data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_data_contents(krb5_context context, krb5_data *val) +{ + if (val == NULL) + return; + if (val->data) { + free(val->data); + val->data = 0; + } +} + +void KRB5_CALLCONV +krb5_free_enc_data(krb5_context context, krb5_enc_data *val) +{ + if (val == NULL) + return; + krb5_free_data_contents(context, &val->ciphertext); + free(val); +} + +void krb5_free_etype_info(krb5_context context, krb5_etype_info info) +{ + int i; + + if (info == NULL) + return; + for (i=0; info[i] != NULL; i++) { + 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 == NULL) + return; + krb5_free_keyblock(context, val->session); + krb5_free_last_req(context, val->last_req); + krb5_free_principal(context, val->server); + krb5_free_addresses(context, val->caddrs); + krb5_free_pa_data(context, val->enc_padata); + free(val); +} + +void KRB5_CALLCONV +krb5_free_enc_tkt_part(krb5_context context, krb5_enc_tkt_part *val) +{ + if (val == NULL) + return; + krb5_free_keyblock(context, val->session); + krb5_free_principal(context, val->client); + free(val->transited.tr_contents.data); + krb5_free_addresses(context, val->caddrs); + krb5_free_authdata(context, val->authorization_data); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_error(krb5_context context, register krb5_error *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->client); + krb5_free_principal(context, val->server); + free(val->text.data); + free(val->e_data.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *val) +{ + if (val == NULL) + return; + krb5_free_pa_data(context, val->padata); + krb5_free_principal(context, val->client); + krb5_free_ticket(context, val->ticket); + free(val->enc_part.ciphertext.data); + krb5_free_enc_kdc_rep_part(context, val->enc_part2); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_kdc_req(krb5_context context, krb5_kdc_req *val) +{ + if (val == NULL) + return; + assert( val->kdc_state == NULL); + krb5_free_pa_data(context, val->padata); + krb5_free_principal(context, val->client); + krb5_free_principal(context, val->server); + free(val->ktype); + krb5_free_addresses(context, val->addresses); + free(val->authorization_data.ciphertext.data); + krb5_free_authdata(context, val->unenc_authdata); + krb5_free_tickets(context, val->second_ticket); + free(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; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) + free(*temp); + free(val); +} + +void KRB5_CALLCONV +krb5_free_pa_data(krb5_context context, krb5_pa_data **val) +{ + register krb5_pa_data **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(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); + free(val->data); + } + free(val->realm.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_priv(krb5_context context, register krb5_priv *val) +{ + if (val == NULL) + return; + free(val->enc_part.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_priv_enc_part(krb5_context context, register krb5_priv_enc_part *val) +{ + if (val == NULL) + return; + free(val->user_data.data); + krb5_free_address(context, val->r_address); + krb5_free_address(context, val->s_address); + free(val); +} + +void KRB5_CALLCONV +krb5_free_pwd_data(krb5_context context, krb5_pwd_data *val) +{ + if (val == NULL) + return; + krb5_free_pwd_sequences(context, val->element); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_passwd_phrase_element(krb5_context context, + passwd_phrase_element *val) +{ + register passwd_phrase_element **temp; + + if (val == NULL) + return; + krb5_free_data(context, val->passwd); + val->passwd = NULL; + krb5_free_data(context, val->phrase); + val->phrase = NULL; + free(val); +} + + +void KRB5_CALLCONV +krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val) +{ + register passwd_phrase_element **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) + krb5_free_passwd_phrase_element(context, *temp); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_safe(krb5_context context, register krb5_safe *val) +{ + if (val == NULL) + return; + free(val->user_data.data); + krb5_free_address(context, val->r_address); + krb5_free_address(context, val->s_address); + krb5_free_checksum(context, val->checksum); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_ticket(krb5_context context, krb5_ticket *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->server); + free(val->enc_part.ciphertext.data); + krb5_free_enc_tkt_part(context, val->enc_part2); + free(val); +} + +void KRB5_CALLCONV +krb5_free_tickets(krb5_context context, krb5_ticket **val) +{ + register krb5_ticket **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) + krb5_free_ticket(context, *temp); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts) +{ + register krb5_creds **tgtpp; + if (tgts == NULL) + return; + for (tgtpp = tgts; *tgtpp; tgtpp++) + krb5_free_creds(context, *tgtpp); + free(tgts); +} + +void KRB5_CALLCONV +krb5_free_tkt_authent(krb5_context context, krb5_tkt_authent *val) +{ + if (val == NULL) + return; + krb5_free_ticket(context, val->ticket); + krb5_free_authenticator(context, val->authenticator); + free(val); +} + +void KRB5_CALLCONV +krb5_free_unparsed_name(krb5_context context, char *val) +{ + free(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); + free(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); + free(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); + free(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++; + } + free(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); + free(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); + free(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); + free(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); + free(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); + 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); + free(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); + free(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; + free(pa_enc_ts); +} + +void KRB5_CALLCONV +krb5_free_pa_for_user(krb5_context context, krb5_pa_for_user *req) +{ + if (req == NULL) + return; + krb5_free_principal(context, req->user); + req->user = NULL; + krb5_free_checksum_contents(context, &req->cksum); + krb5_free_data_contents(context, &req->auth_package); + free(req); +} + +void KRB5_CALLCONV +krb5_free_pa_server_referral_data(krb5_context context, + krb5_pa_server_referral_data *ref) +{ + if (ref == NULL) + return; + krb5_free_data(context, ref->referred_realm); + ref->referred_realm = NULL; + krb5_free_principal(context, ref->true_principal_name); + ref->true_principal_name = NULL; + krb5_free_principal(context, ref->requested_principal_name); + ref->requested_principal_name = NULL; + krb5_free_checksum_contents(context, &ref->rep_cksum); + free(ref); +} + +void KRB5_CALLCONV +krb5_free_pa_svr_referral_data(krb5_context context, + krb5_pa_svr_referral_data *ref) +{ + if (ref == NULL) + return; + krb5_free_principal(context, ref->principal); + ref->principal = NULL; + free(ref); +} + +void KRB5_CALLCONV +krb5_free_pa_pac_req(krb5_context context, + krb5_pa_pac_req *req) +{ + free(req); +} + +void KRB5_CALLCONV +krb5_free_etype_list(krb5_context context, + krb5_etype_list *etypes) +{ + if (etypes != NULL) { + free(etypes->etypes); + free(etypes); + } +} +void krb5_free_fast_req(krb5_context context, krb5_fast_req *val) +{ + if (val == NULL) + return; + krb5_free_kdc_req(context, val->req_body); + free(val); +} + +void krb5_free_fast_armor(krb5_context context, krb5_fast_armor *val) +{ + if (val == NULL) + return; + krb5_free_data_contents(context, &val->armor_value); + free(val); +} + +void krb5_free_fast_response(krb5_context context, krb5_fast_response *val) +{ + if (!val) + return; + krb5_free_pa_data(context, val->padata); + krb5_free_fast_finished(context, val->finished); + krb5_free_keyblock(context, val->strengthen_key); + free(val); +} + +void krb5_free_fast_finished +(krb5_context context, krb5_fast_finished *val) +{ + if (!val) + return; + krb5_free_principal(context, val->client); + krb5_free_checksum_contents(context, &val->ticket_checksum); + free(val); +} + +void krb5_free_typed_data(krb5_context context, 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 krb5_free_fast_armored_req(krb5_context context, + krb5_fast_armored_req *val) +{ + if (val == NULL) + return; + if (val->armor) + krb5_free_fast_armor(context, val->armor); + krb5_free_data_contents(context, &val->enc_part.ciphertext); + if (val->req_checksum.contents) + krb5_free_checksum_contents(context, &val->req_checksum); + free(val); +} diff --git a/krb5-1-7/src/lib/krb5/krb/mk_cred.c b/krb5-1-7/src/lib/krb5/krb/mk_cred.c new file mode 100644 index 000000000..f17a14858 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_cred.c @@ -0,0 +1,315 @@ +/* + * 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 /* NULL */ +#include /* malloc */ +#include /* 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; + free(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 **) calloc(1, size); + if (credenc.ticket_info == NULL) + return ENOMEM; + + /* + * 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; + krb5_boolean increased_sequence = FALSE; + + 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 *)calloc(1, sizeof(krb5_cred))) == NULL) + return ENOMEM; + + if ((pcred->tickets + = (krb5_ticket **)calloc((size_t)ncred+1, + sizeof(krb5_ticket *))) == NULL) { + retval = ENOMEM; + goto error; + } + + /* 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)) { + retval = KRB5_RC_REQUIRED; + goto error; + } + + 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 */ + retval = KRB5_RC_REQUIRED; + goto error; + } + + if ((retval = krb5_us_timeofday(context, &replaydata.timestamp, + &replaydata.usec))) + goto error; + 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++; + increased_sequence = TRUE; + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) + 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.msghash = NULL; + 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 */ + free(replay.client); + goto error; + } + free(replay.client); + } + + /* Encode creds structure */ + retval = encode_krb5_cred(pcred, ppdata); + +error: + free(local_fulladdr.contents); + free(remote_fulladdr.contents); + krb5_free_cred(context, pcred); + + if (retval) { + if (increased_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-7/src/lib/krb5/krb/mk_error.c b/krb5-1-7/src/lib/krb5/krb/mk_error.c new file mode 100644 index 000000000..75cdc9b5b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_error.c @@ -0,0 +1,52 @@ +/* + * 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; + free(new_enc_err); + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/mk_priv.c b/krb5-1-7/src/lib/krb5/krb/mk_priv.c new file mode 100644 index 000000000..727262cbe --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_priv.c @@ -0,0 +1,235 @@ +/* + * 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; + free(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->local_addr) + return KRB5_LOCAL_ADDR_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; + krb5_address remote_fulladdr; + krb5_address local_fulladdr; + CLEANUP_INIT(2); + + 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))) { + free(outbuf); + goto error; + } + + replay.server = ""; /* XXX */ + replay.msghash = NULL; + 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 */ + free(replay.client); + goto error; + } + free(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-7/src/lib/krb5/krb/mk_rep.c b/krb5-1-7/src/lib/krb5/krb/mk_rep.c new file mode 100644 index 000000000..29155b6e1 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_rep.c @@ -0,0 +1,150 @@ +/* + * 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() + */ +/* + * Copyright (c) 2006-2008, 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" +#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 +*/ + +static krb5_error_code +k5_mk_rep(krb5_context context, krb5_auth_context auth_context, + krb5_data *outbuf, int dce_style) +{ + 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); + } + + if (dce_style) { + krb5_us_timeofday(context, &repl.ctime, &repl.cusec); + } else { + repl.ctime = auth_context->authentp->ctime; + repl.cusec = auth_context->authentp->cusec; + } + + if (dce_style) + repl.subkey = NULL; + else if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { + assert(auth_context->negotiated_etype != ENCTYPE_NULL); + + retval = krb5int_generate_and_save_subkey (context, auth_context, + auth_context->keyblock, + auth_context->negotiated_etype); + if (retval) + return retval; + repl.subkey = auth_context->send_subkey; + } else + repl.subkey = auth_context->authentp->subkey; + + if (dce_style) + repl.seq_number = auth_context->remote_seq_number; + else + 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; + free(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; +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) +{ + return k5_mk_rep(context, auth_context, outbuf, 0); +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) +{ + return k5_mk_rep(context, auth_context, outbuf, 1); +} diff --git a/krb5-1-7/src/lib/krb5/krb/mk_req.c b/krb5-1-7/src/lib/krb5/krb/mk_req.c new file mode 100644 index 000000000..2935e41b3 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/mk_req_ext.c b/krb5-1-7/src/lib/krb5/krb/mk_req_ext.c new file mode 100644 index 000000000..b2f65535f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_req_ext.c @@ -0,0 +1,418 @@ +/* + * 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 +make_etype_list(krb5_context context, + krb5_enctype *desired_etypes, + krb5_enctype tkt_enctype, + krb5_authdata ***authdata); + +static krb5_error_code +krb5_generate_authenticator (krb5_context, + krb5_authenticator *, krb5_principal, + krb5_checksum *, krb5_keyblock *, + krb5_ui_4, krb5_authdata **, + krb5_enctype *desired_etypes, + krb5_enctype tkt_enctype); + +krb5_error_code +krb5int_generate_and_save_subkey (krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock, + krb5_enctype enctype) +{ + /* 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_extended(context, keyblock, enctype, + &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_enctype *desired_etypes = NULL; + + 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 = NULL; + request.ticket = 0; + + if (!in_creds->ticket.length) + return(KRB5_NO_TKT_SUPPLIED); + + if ((ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) && + !(ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) + return(EINVAL); + + /* 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, + in_creds->keyblock.enctype); + 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 { + krb5_cksumtype cksumtype; + retval = krb5int_c_mandatory_cksumtype(context, (*auth_context)->keyblock->enctype, + &cksumtype); + if (retval) + goto cleanup_cksum; + if ((*auth_context)->req_cksumtype) + cksumtype = (*auth_context)->req_cksumtype; + if ((retval = krb5_c_make_checksum(context, + 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 (ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) { + if ((*auth_context)->permitted_etypes == NULL) { + retval = krb5_get_tgs_ktypes(context, in_creds->server, &desired_etypes); + if (retval) + goto cleanup_cksum; + } else + desired_etypes = (*auth_context)->permitted_etypes; + } + + 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, + desired_etypes, + in_creds->keyblock.enctype))) + 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; + + /* 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; + + free(toutbuf); + +cleanup_cksum: + if (checksump && checksump->checksum_type != 0x8003) + free(checksump->contents); + +cleanup: + if (desired_etypes && + desired_etypes != (*auth_context)->permitted_etypes) + free(desired_etypes); + 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); + free(scratch->data); + free(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_enctype *desired_etypes, + krb5_enctype tkt_enctype) +{ + 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 = NULL; + + if (authorization != NULL) { + retval = krb5_copy_authdata(context, authorization, + &authent->authorization_data); + if (retval) + return retval; + } + /* Only send EtypeList if we prefer another enctype to tkt_enctype */ + if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) { + retval = make_etype_list(context, desired_etypes, tkt_enctype, + &authent->authorization_data); + if (retval) + return retval; + } + + return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec)); +} + +/* RFC 4537 */ +static krb5_error_code +make_etype_list(krb5_context context, + krb5_enctype *desired_etypes, + krb5_enctype tkt_enctype, + krb5_authdata ***authdata) +{ + krb5_error_code code; + krb5_etype_list etypes; + krb5_data *enc_etype_list; + krb5_data *ad_if_relevant; + krb5_authdata *etype_adata[2], etype_adatum, **adata; + int i; + + etypes.etypes = desired_etypes; + + for (etypes.length = 0; + etypes.etypes[etypes.length] != ENCTYPE_NULL; + etypes.length++) + { + /* + * RFC 4537: + * + * If the enctype of the ticket session key is included in the enctype + * list sent by the client, it SHOULD be the last on the list; + */ + if (etypes.length && etypes.etypes[etypes.length - 1] == tkt_enctype) + break; + } + + code = encode_krb5_etype_list(&etypes, &enc_etype_list); + if (code) { + return code; + } + + etype_adatum.magic = KV5M_AUTHDATA; + etype_adatum.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION; + etype_adatum.length = enc_etype_list->length; + etype_adatum.contents = (krb5_octet *)enc_etype_list->data; + + etype_adata[0] = &etype_adatum; + etype_adata[1] = NULL; + + /* Wrap in AD-IF-RELEVANT container */ + code = encode_krb5_authdata(etype_adata, &ad_if_relevant); + if (code) { + krb5_free_data(context, enc_etype_list); + return code; + } + + krb5_free_data(context, enc_etype_list); + + adata = *authdata; + if (adata == NULL) { + adata = (krb5_authdata **)calloc(2, sizeof(krb5_authdata *)); + i = 0; + } else { + for (i = 0; adata[i] != NULL; i++) + ; + + adata = (krb5_authdata **)realloc(*authdata, + (i + 2) * sizeof(krb5_authdata *)); + } + if (adata == NULL) { + krb5_free_data(context, ad_if_relevant); + return ENOMEM; + } + *authdata = adata; + + adata[i] = (krb5_authdata *)malloc(sizeof(krb5_authdata)); + if (adata[i] == NULL) { + krb5_free_data(context, ad_if_relevant); + return ENOMEM; + } + adata[i]->magic = KV5M_AUTHDATA; + adata[i]->ad_type = KRB5_AUTHDATA_IF_RELEVANT; + adata[i]->length = ad_if_relevant->length; + adata[i]->contents = (krb5_octet *)ad_if_relevant->data; + free(ad_if_relevant); /* contents owned by adata[i] */ + + adata[i + 1] = NULL; + + return 0; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/mk_safe.c b/krb5-1-7/src/lib/krb5/krb/mk_safe.c new file mode 100644 index 000000000..0afa61e85 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/mk_safe.c @@ -0,0 +1,261 @@ +/* + * 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; + free(scratch2); + retval = 0; + +cleanup_checksum: + free(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->local_addr) + return KRB5_LOCAL_ADDR_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; + krb5_address remote_fulladdr; + krb5_address local_fulladdr; + krb5_cksumtype sumtype; + + CLEANUP_INIT(2); + + 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))) { + free(outbuf); + goto error; + } + + replay.server = ""; /* XXX */ + replay.msghash = NULL; + 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 */ + free(outbuf); + goto error; + } + free(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-7/src/lib/krb5/krb/pac.c b/krb5-1-7/src/lib/krb5/krb/pac.c new file mode 100644 index 000000000..c5a706562 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/pac.c @@ -0,0 +1,872 @@ +/* + * lib/krb5/krb/pac.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 "k5-utf8.h" + +/* draft-brezak-win2k-krb-authz-00 */ + +/* + * A PAC consists of a sequence of PAC_INFO_BUFFERs, preceeded by + * a PACTYPE header. Decoding the contents of the buffers is left + * to the application (notwithstanding signature verification). + */ + +typedef struct _PAC_INFO_BUFFER { + krb5_ui_4 ulType; + krb5_ui_4 cbBufferSize; + krb5_ui_8 Offset; +} PAC_INFO_BUFFER; + +#define PAC_INFO_BUFFER_LENGTH 16 + +/* ulType */ +#define PAC_LOGON_INFO 1 +#define PAC_SERVER_CHECKSUM 6 +#define PAC_PRIVSVR_CHECKSUM 7 +#define PAC_CLIENT_INFO 10 + +typedef struct _PACTYPE { + krb5_ui_4 cBuffers; + krb5_ui_4 Version; + PAC_INFO_BUFFER Buffers[1]; +} PACTYPE; + +#define PAC_ALIGNMENT 8 +#define PACTYPE_LENGTH 8U +#define PAC_SIGNATURE_DATA_LENGTH 4U +#define PAC_CLIENT_INFO_LENGTH 10U + +#define NT_TIME_EPOCH 11644473600LL + +struct krb5_pac_data { + PACTYPE *pac; /* PAC header + info buffer array */ + krb5_data data; /* PAC data (including uninitialised header) */ +}; + +static krb5_error_code +k5_pac_locate_buffer(krb5_context context, + const krb5_pac pac, + krb5_ui_4 type, + krb5_data *data); + +/* + * Add a buffer to the provided PAC and update header. + */ +static krb5_error_code +k5_pac_add_buffer(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_data *data, + krb5_boolean zerofill, + krb5_data *out_data) +{ + PACTYPE *header; + size_t header_len, i, pad = 0; + char *pac_data; + + assert((data->data == NULL) == zerofill); + + /* Check there isn't already a buffer of this type */ + if (k5_pac_locate_buffer(context, pac, type, NULL) == 0) { + return EINVAL; + } + + header = (PACTYPE *)realloc(pac->pac, + sizeof(PACTYPE) + + (pac->pac->cBuffers * sizeof(PAC_INFO_BUFFER))); + if (header == NULL) { + return ENOMEM; + } + pac->pac = header; + + header_len = PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH); + + if (data->length % PAC_ALIGNMENT) + pad = PAC_ALIGNMENT - (data->length % PAC_ALIGNMENT); + + pac_data = realloc(pac->data.data, + pac->data.length + PAC_INFO_BUFFER_LENGTH + data->length + pad); + if (pac_data == NULL) { + return ENOMEM; + } + pac->data.data = pac_data; + + /* Update offsets of existing buffers */ + for (i = 0; i < pac->pac->cBuffers; i++) + pac->pac->Buffers[i].Offset += PAC_INFO_BUFFER_LENGTH; + + /* Make room for new PAC_INFO_BUFFER */ + memmove(pac->data.data + header_len + PAC_INFO_BUFFER_LENGTH, + pac->data.data + header_len, + pac->data.length - header_len); + memset(pac->data.data + header_len, 0, PAC_INFO_BUFFER_LENGTH); + + /* Initialise new PAC_INFO_BUFFER */ + pac->pac->Buffers[i].ulType = type; + pac->pac->Buffers[i].cbBufferSize = data->length; + pac->pac->Buffers[i].Offset = pac->data.length + PAC_INFO_BUFFER_LENGTH; + assert((pac->pac->Buffers[i].Offset % PAC_ALIGNMENT) == 0); + + /* Copy in new PAC data and zero padding bytes */ + if (zerofill) + memset(pac->data.data + pac->pac->Buffers[i].Offset, 0, data->length); + else + memcpy(pac->data.data + pac->pac->Buffers[i].Offset, data->data, data->length); + + memset(pac->data.data + pac->pac->Buffers[i].Offset + data->length, 0, pad); + + pac->pac->cBuffers++; + pac->data.length += PAC_INFO_BUFFER_LENGTH + data->length + pad; + + if (out_data != NULL) { + out_data->data = pac->data.data + pac->pac->Buffers[i].Offset; + out_data->length = data->length; + } + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_add_buffer(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_data *data) +{ + return k5_pac_add_buffer(context, pac, type, data, FALSE, NULL); +} + +/* + * Free a PAC + */ +void KRB5_CALLCONV +krb5_pac_free(krb5_context context, + krb5_pac pac) +{ + if (pac != NULL) { + if (pac->data.data != NULL) { + memset(pac->data.data, 0, pac->data.length); + free(pac->data.data); + } + if (pac->pac != NULL) + free(pac->pac); + memset(pac, 0, sizeof(*pac)); + free(pac); + } +} + +static krb5_error_code +k5_pac_locate_buffer(krb5_context context, + const krb5_pac pac, + krb5_ui_4 type, + krb5_data *data) +{ + PAC_INFO_BUFFER *buffer = NULL; + size_t i; + + if (pac == NULL) + return EINVAL; + + for (i = 0; i < pac->pac->cBuffers; i++) { + if (pac->pac->Buffers[i].ulType == type) { + if (buffer == NULL) + buffer = &pac->pac->Buffers[i]; + else + return EINVAL; + } + } + + if (buffer == NULL) + return ENOENT; + + assert(buffer->Offset + buffer->cbBufferSize <= pac->data.length); + + if (data != NULL) { + data->length = buffer->cbBufferSize; + data->data = pac->data.data + buffer->Offset; + } + + return 0; +} + +/* + * Find a buffer and copy data into output + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_buffer(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + krb5_data *data) +{ + krb5_data d; + krb5_error_code ret; + + ret = k5_pac_locate_buffer(context, pac, type, &d); + if (ret != 0) + return ret; + + data->data = malloc(d.length); + if (data->data == NULL) + return ENOMEM; + + data->length = d.length; + memcpy(data->data, d.data, d.length); + + return 0; +} + +/* + * Return an array of the types of data in the PAC + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_types(krb5_context context, + krb5_pac pac, + size_t *len, + krb5_ui_4 **types) +{ + size_t i; + + *types = (krb5_ui_4 *)malloc(pac->pac->cBuffers * sizeof(krb5_ui_4)); + if (*types == NULL) + return ENOMEM; + + *len = pac->pac->cBuffers; + + for (i = 0; i < pac->pac->cBuffers; i++) + (*types)[i] = pac->pac->Buffers[i].ulType; + + return 0; +} + +/* + * Initialize PAC + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_init(krb5_context context, + krb5_pac *ppac) +{ + krb5_pac pac; + + pac = (krb5_pac)malloc(sizeof(*pac)); + if (pac == NULL) + return ENOMEM; + + pac->pac = (PACTYPE *)malloc(sizeof(PACTYPE)); + if (pac->pac == NULL) { + free( pac); + return ENOMEM; + } + + pac->pac->cBuffers = 0; + pac->pac->Version = 0; + + pac->data.length = PACTYPE_LENGTH; + pac->data.data = calloc(1, pac->data.length); + if (pac->data.data == NULL) { + krb5_pac_free(context, pac); + return ENOMEM; + } + + *ppac = pac; + + return 0; +} + +/* + * Parse the supplied data into the PAC allocated by this function + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_parse(krb5_context context, + const void *ptr, + size_t len, + krb5_pac *ppac) +{ + krb5_error_code ret; + size_t i; + const unsigned char *p = (const unsigned char *)ptr; + krb5_pac pac; + size_t header_len; + krb5_ui_4 cbuffers, version; + + *ppac = NULL; + + if (len < PACTYPE_LENGTH) + return ERANGE; + + cbuffers = load_32_le(p); + p += 4; + version = load_32_le(p); + p += 4; + + if (version != 0) + return EINVAL; + + header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH); + if (len < header_len) + return ERANGE; + + ret = krb5_pac_init(context, &pac); + if (ret != 0) + return ret; + + pac->pac = (PACTYPE *)realloc(pac->pac, + sizeof(PACTYPE) + ((cbuffers - 1) * sizeof(PAC_INFO_BUFFER))); + if (pac->pac == NULL) { + krb5_pac_free(context, pac); + return ENOMEM; + } + + pac->pac->cBuffers = cbuffers; + pac->pac->Version = version; + + for (i = 0; i < pac->pac->cBuffers; i++) { + PAC_INFO_BUFFER *buffer = &pac->pac->Buffers[i]; + + buffer->ulType = load_32_le(p); + p += 4; + buffer->cbBufferSize = load_32_le(p); + p += 4; + buffer->Offset = load_64_le(p); + p += 8; + + if (buffer->Offset % PAC_ALIGNMENT) { + krb5_pac_free(context, pac); + return EINVAL; + } + if (buffer->Offset < header_len || + buffer->Offset + buffer->cbBufferSize > len) { + krb5_pac_free(context, pac); + return ERANGE; + } + } + + pac->data.data = realloc(pac->data.data, len); + if (pac->data.data == NULL) { + krb5_pac_free(context, pac); + return ENOMEM; + } + memcpy(pac->data.data, ptr, len); + + pac->data.length = len; + + *ppac = pac; + + return 0; +} + +static krb5_error_code +k5_time_to_seconds_since_1970(krb5_int64 ntTime, krb5_timestamp *elapsedSeconds) +{ + krb5_ui_8 abstime; + + ntTime /= 10000000; + + abstime = ntTime > 0 ? ntTime - NT_TIME_EPOCH : -ntTime; + + if (abstime > KRB5_INT32_MAX) + return ERANGE; + + *elapsedSeconds = abstime; + + return 0; +} + +static krb5_error_code +k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, krb5_ui_8 *ntTime) +{ + *ntTime = elapsedSeconds; + + if (elapsedSeconds > 0) + *ntTime += NT_TIME_EPOCH; + + *ntTime *= 10000000; + + return 0; +} + +static krb5_error_code +k5_pac_validate_client(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal) +{ + krb5_error_code ret; + krb5_data client_info; + char *pac_princname; + unsigned char *p; + krb5_timestamp pac_authtime; + krb5_ui_2 pac_princname_length; + krb5_int64 pac_nt_authtime; + krb5_principal pac_principal; + + ret = k5_pac_locate_buffer(context, pac, PAC_CLIENT_INFO, &client_info); + if (ret != 0) + return ret; + + if (client_info.length < PAC_CLIENT_INFO_LENGTH) + return ERANGE; + + p = (unsigned char *)client_info.data; + pac_nt_authtime = load_64_le(p); + p += 8; + pac_princname_length = load_16_le(p); + p += 2; + + ret = k5_time_to_seconds_since_1970(pac_nt_authtime, &pac_authtime); + if (ret != 0) + return ret; + + if (client_info.length < PAC_CLIENT_INFO_LENGTH + pac_princname_length || + pac_princname_length % 2) + return ERANGE; + + ret = krb5int_ucs2lecs_to_utf8s(p, (size_t)pac_princname_length / 2, &pac_princname, NULL); + if (ret != 0) + return ret; + + ret = krb5_parse_name_flags(context, pac_princname, 0, &pac_principal); + if (ret != 0) { + free(pac_princname); + return ret; + } + + free(pac_princname); + + if (pac_authtime != authtime || + krb5_principal_compare(context, pac_principal, principal) == FALSE) + ret = KRB5KRB_AP_WRONG_PRINC; + + krb5_free_principal(context, pac_principal); + + return ret; +} + +static krb5_error_code +k5_pac_zero_signature(krb5_context context, + const krb5_pac pac, + krb5_ui_4 type, + krb5_data *data) +{ + PAC_INFO_BUFFER *buffer = NULL; + size_t i; + + assert(type == PAC_SERVER_CHECKSUM || type == PAC_PRIVSVR_CHECKSUM); + assert(data->length >= pac->data.length); + + for (i = 0; i < pac->pac->cBuffers; i++) { + if (pac->pac->Buffers[i].ulType == type) { + buffer = &pac->pac->Buffers[i]; + break; + } + } + + if (buffer == NULL) + return ENOENT; + + if (buffer->Offset + buffer->cbBufferSize > pac->data.length) + return ERANGE; + + if (buffer->cbBufferSize < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + + /* Zero out the data portion of the checksum only */ + memset(data->data + buffer->Offset + PAC_SIGNATURE_DATA_LENGTH, + 0, + buffer->cbBufferSize - PAC_SIGNATURE_DATA_LENGTH); + + return 0; +} + +static krb5_error_code +k5_pac_verify_server_checksum(krb5_context context, + const krb5_pac pac, + const krb5_keyblock *server) +{ + krb5_error_code ret; + krb5_data pac_data; /* PAC with zeroed checksums */ + krb5_checksum checksum; + krb5_data checksum_data; + krb5_boolean valid; + krb5_octet *p; + + ret = k5_pac_locate_buffer(context, pac, PAC_SERVER_CHECKSUM, &checksum_data); + if (ret != 0) + return ret; + + if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + + p = (krb5_octet *)checksum_data.data; + checksum.checksum_type = load_32_le(p); + checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + + pac_data.length = pac->data.length; + pac_data.data = malloc(pac->data.length); + if (pac_data.data == NULL) + return ENOMEM; + + memcpy(pac_data.data, pac->data.data, pac->data.length); + + /* Zero out both checksum buffers */ + ret = k5_pac_zero_signature(context, pac, PAC_SERVER_CHECKSUM, &pac_data); + if (ret != 0) { + free(pac_data.data); + return ret; + } + + ret = k5_pac_zero_signature(context, pac, PAC_PRIVSVR_CHECKSUM, &pac_data); + if (ret != 0) { + free(pac_data.data); + return ret; + } + + ret = krb5_c_verify_checksum(context, server, KRB5_KEYUSAGE_APP_DATA_CKSUM, + &pac_data, &checksum, &valid); + + free(pac_data.data); + + if (ret != 0) { + return ret; + } + + if (valid == FALSE) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + + return ret; +} + +static krb5_error_code +k5_pac_verify_kdc_checksum(krb5_context context, + const krb5_pac pac, + const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + krb5_data server_checksum, privsvr_checksum; + krb5_checksum checksum; + krb5_boolean valid; + krb5_octet *p; + + ret = k5_pac_locate_buffer(context, pac, PAC_PRIVSVR_CHECKSUM, &privsvr_checksum); + if (ret != 0) + return ret; + + if (privsvr_checksum.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + + ret = k5_pac_locate_buffer(context, pac, PAC_SERVER_CHECKSUM, &server_checksum); + if (ret != 0) + return ret; + + if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + + p = (krb5_octet *)privsvr_checksum.data; + checksum.checksum_type = load_32_le(p); + checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_verify_checksum(context, privsvr, KRB5_KEYUSAGE_APP_DATA_CKSUM, + &server_checksum, &checksum, &valid); + if (ret != 0) + return ret; + + if (valid == FALSE) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_verify(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + + if (server == NULL) + return EINVAL; + + ret = k5_pac_verify_server_checksum(context, pac, server); + if (ret != 0) + return ret; + + if (privsvr != NULL) { + ret = k5_pac_verify_kdc_checksum(context, pac, privsvr); + if (ret != 0) + return ret; + } + + if (principal != NULL) { + ret = k5_pac_validate_client(context, pac, authtime, principal); + if (ret != 0) + return ret; + } + + return 0; +} + +static krb5_error_code +k5_insert_client_info(krb5_context context, + krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal) +{ + krb5_error_code ret; + krb5_data client_info; + char *princ_name_utf8 = NULL; + unsigned char *princ_name_ucs2 = NULL, *p; + size_t princ_name_ucs2_len = 0; + krb5_ui_8 nt_authtime; + + /* If we already have a CLIENT_INFO buffer, then just validate it */ + if (k5_pac_locate_buffer(context, pac, PAC_CLIENT_INFO, &client_info) == 0) { + return k5_pac_validate_client(context, pac, authtime, principal); + } + + ret = krb5_unparse_name_flags(context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &princ_name_utf8); + if (ret != 0) + goto cleanup; + + ret = krb5int_utf8s_to_ucs2les(princ_name_utf8, + &princ_name_ucs2, + &princ_name_ucs2_len); + if (ret != 0) + goto cleanup; + + client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_ucs2_len; + client_info.data = NULL; + + ret = k5_pac_add_buffer(context, pac, PAC_CLIENT_INFO, &client_info, TRUE, &client_info); + if (ret != 0) + goto cleanup; + + p = (unsigned char *)client_info.data; + + /* copy in authtime converted to a 64-bit NT time */ + k5_seconds_since_1970_to_time(authtime, &nt_authtime); + store_64_le(nt_authtime, p); + p += 8; + + /* copy in number of UCS-2 characters in principal name */ + store_16_le(princ_name_ucs2_len, p); + p += 2; + + /* copy in principal name */ + memcpy(p, princ_name_ucs2, princ_name_ucs2_len); + +cleanup: + if (princ_name_utf8 != NULL) + free(princ_name_utf8); + if (princ_name_ucs2 != NULL) + free(princ_name_ucs2); + + return ret; +} + +static krb5_error_code +k5_insert_checksum(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_keyblock *key, + krb5_cksumtype *cksumtype) +{ + krb5_error_code ret; + size_t len; + krb5_data cksumdata; + + ret = krb5int_c_mandatory_cksumtype(context, key->enctype, cksumtype); + if (ret != 0) + return ret; + + ret = krb5_c_checksum_length(context, *cksumtype, &len); + if (ret != 0) + return ret; + + ret = k5_pac_locate_buffer(context, pac, type, &cksumdata); + if (ret == 0) { + /* If we're resigning PAC, make sure we can fit checksum into existing buffer */ + if (cksumdata.length != PAC_SIGNATURE_DATA_LENGTH + len) + return ERANGE; + + memset(cksumdata.data, 0, cksumdata.length); + } else { + /* Add a zero filled buffer */ + cksumdata.length = PAC_SIGNATURE_DATA_LENGTH + len; + cksumdata.data = NULL; + + ret = k5_pac_add_buffer(context, pac, type, &cksumdata, TRUE, &cksumdata); + if (ret != 0) + return ret; + } + + /* Encode checksum type into buffer */ + store_32_le((krb5_ui_4)*cksumtype, cksumdata.data); + + return 0; +} + +/* in-place encoding of PAC header */ +static krb5_error_code +k5_pac_encode_header(krb5_context context, krb5_pac pac) +{ + size_t i; + unsigned char *p; + size_t header_len; + + header_len = PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH); + assert(pac->data.length >= header_len); + + p = (unsigned char *)pac->data.data; + + store_32_le(pac->pac->cBuffers, p); + p += 4; + store_32_le(pac->pac->Version, p); + p += 4; + + for (i = 0; i < pac->pac->cBuffers; i++) { + PAC_INFO_BUFFER *buffer = &pac->pac->Buffers[i]; + + store_32_le(buffer->ulType, p); + p += 4; + store_32_le(buffer->cbBufferSize, p); + p += 4; + store_64_le(buffer->Offset, p); + p += 8; + + assert((buffer->Offset % PAC_ALIGNMENT) == 0); + assert(buffer->Offset + buffer->cbBufferSize <= pac->data.length); + assert(buffer->Offset >= header_len); + + if (buffer->Offset % PAC_ALIGNMENT || + buffer->Offset + buffer->cbBufferSize > pac->data.length || + buffer->Offset < header_len) + return ERANGE; + } + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5int_pac_sign(krb5_context context, + krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data server_cksum, privsvr_cksum; + krb5_cksumtype server_cksumtype, privsvr_cksumtype; + krb5_crypto_iov iov[2]; + + data->length = 0; + data->data = NULL; + + if (principal != NULL) { + ret = k5_insert_client_info(context, pac, authtime, principal); + if (ret != 0) + return ret; + } + + /* Create zeroed buffers for both checksums */ + ret = k5_insert_checksum(context, pac, PAC_SERVER_CHECKSUM, + server_key, &server_cksumtype); + if (ret != 0) + return ret; + + ret = k5_insert_checksum(context, pac, PAC_PRIVSVR_CHECKSUM, + privsvr_key, &privsvr_cksumtype); + if (ret != 0) + return ret; + + /* Now, encode the PAC header so that the checksums will include it */ + ret = k5_pac_encode_header(context, pac); + if (ret != 0) + return ret; + + /* Generate the server checksum over the entire PAC */ + ret = k5_pac_locate_buffer(context, pac, PAC_SERVER_CHECKSUM, &server_cksum); + if (ret != 0) + return ret; + + assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH); + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = pac->data; + + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_make_checksum_iov(context, server_cksumtype, + server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + return ret; + + /* Generate the privsvr checksum over the server checksum buffer */ + ret = k5_pac_locate_buffer(context, pac, PAC_PRIVSVR_CHECKSUM, &privsvr_cksum); + if (ret != 0) + return ret; + + assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH); + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype, + privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + return ret; + + data->data = malloc(pac->data.length); + if (data->data == NULL) + return ENOMEM; + + data->length = pac->data.length; + + memcpy(data->data, pac->data.data, pac->data.length); + memset(pac->data.data, 0, PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH)); + + return 0; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/parse.c b/krb5-1-7/src/lib/krb5/krb/parse.c new file mode 100644 index 000000000..d55a488e3 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/parse.c @@ -0,0 +1,340 @@ +/* + * lib/krb5/krb/parse.c + * + * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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..... + */ +static krb5_error_code +k5_parse_name(krb5_context context, const char *name, + int flags, 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; + unsigned int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); + int first_at; + + *nprincipal = NULL; + + /* + * Pass 1. Find out how many components there are to the name, + * and get string sizes for the first FCOMPNUM components. For + * enterprise principal names (UPNs), there is only a single + * component. + */ + size = 0; + for (i=0,cp = name, first_at = 1; (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 && !enterprise) { + 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 && (!enterprise || !first_at)) { + 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 { + if (c == REALM_SEP && enterprise && first_at) + first_at = 0; + + size++; + } + } + if (parsed_realm != NULL) + 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 == NULL) { + return(ENOMEM); + } + principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components); + if (principal->data == NULL) { + free((char *)principal); + return ENOMEM; + } + principal->length = components; + + /* + * If a realm was not found, then use the default realm, unless + * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the + * realm will be empty. + */ + if (!parsed_realm) { + if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) { + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, + "Principal %s is missing required realm", name); + free(principal->data); + free(principal); + return KRB5_PARSE_MALFORMED; + } + if (!default_realm && (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) == 0) { + retval = krb5_get_default_realm(context, &default_realm); + if (retval) { + free(principal->data); + free((char *)principal); + return(retval); + } + default_realm_size = strlen(default_realm); + } + realmsize = default_realm_size; + } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, + "Principal %s has realm present", name); + free(principal->data); + free(principal); + return KRB5_PARSE_MALFORMED; + } + + /* + * 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..... + */ + 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) { + free(principal->data); + free(principal); + free(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 == NULL) { + for (i--; i >= 0; i--) + free(krb5_princ_component(context, principal, i)->data); + free(krb5_princ_realm(context, principal)->data); + free(principal->data); + free(principal); + free(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, first_at = 1; (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; + break; + } + } else if (c == COMPONENT_SEP && !enterprise) { + i++; + *q++ = '\0'; + q = krb5_princ_component(context, principal, i)->data; + } else if (c == REALM_SEP && (!enterprise || !first_at)) { + i++; + *q++ = '\0'; + q = krb5_princ_realm(context, principal)->data; + } else { + if (c == REALM_SEP && enterprise && first_at) + first_at = 0; + + *q++ = c; + } + } + *q++ = '\0'; + if (!parsed_realm) { + if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) + (krb5_princ_realm(context, principal)->data)[0] = '\0'; + else + strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize+1); + } + /* + * Alright, we're done. Now stuff a pointer to this monstrosity + * into the return variable, and let's get out of here. + */ + if (enterprise) + krb5_princ_type(context, principal) = KRB5_NT_ENTERPRISE_PRINCIPAL; + else + krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL; + principal->magic = KV5M_PRINCIPAL; + principal->realm.magic = KV5M_DATA; + *nprincipal = principal; + + if (default_realm != NULL) + free(default_realm); + + return(0); +} + +krb5_error_code KRB5_CALLCONV +krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal) +{ + return k5_parse_name(context, name, 0, nprincipal); +} + +krb5_error_code KRB5_CALLCONV +krb5_parse_name_flags(krb5_context context, const char *name, + int flags, krb5_principal *nprincipal) +{ + return k5_parse_name(context, name, flags, nprincipal); +} diff --git a/krb5-1-7/src/lib/krb5/krb/pkinit_apple_asn1.c b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_asn1.c new file mode 100644 index 000000000..9082a314b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_asn1.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_asn1.c - ASN.1 encode/decode routines for PKINIT, Mac OS X version + * + * Created 19 May 2004 by Doug Mitchell. + */ + +#if APPLE_PKINIT + +#include "k5-int.h" +#include "pkinit_asn1.h" +#include "pkinit_apple_utils.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma mark ----- utility routines ----- + +/* malloc a NULL-ed array of pointers of size num+1 */ +static void **pkiNssNullArray( + uint32 num, + SecAsn1CoderRef coder) +{ + unsigned len = (num + 1) * sizeof(void *); + void **p = (void **)SecAsn1Malloc(coder, len); + memset(p, 0, len); + return p; +} + +#pragma mark ====== begin PA-PK-AS-REQ components ====== + +#pragma mark ----- pkAuthenticator ----- + +/* + * There is a unique error code for "missing paChecksum", so we mark it here + * as optional so the decoder can process a pkAuthenticator without the + * checksum; caller must verify that paChecksum.Data != NULL. + */ +typedef struct { + CSSM_DATA cusec; /* INTEGER, microseconds */ + CSSM_DATA kctime; /* UTC time (with trailing 'Z') */ + CSSM_DATA nonce; /* INTEGER */ + CSSM_DATA paChecksum; /* OCTET STRING */ +} KRB5_PKAuthenticator; + +static const SecAsn1Template KRB5_PKAuthenticatorTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PKAuthenticator) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_PKAuthenticator,cusec), + kSecAsn1IntegerTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_PKAuthenticator,kctime), + kSecAsn1GeneralizedTimeTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 2, + offsetof(KRB5_PKAuthenticator,nonce), + kSecAsn1IntegerTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | + SEC_ASN1_OPTIONAL | 3, + offsetof(KRB5_PKAuthenticator,paChecksum), + &kSecAsn1OctetStringTemplate }, + { 0 } +}; + +#pragma mark ----- AuthPack ----- + +typedef struct { + KRB5_PKAuthenticator pkAuth; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *pubKeyInfo; /* OPTIONAL */ + CSSM_X509_ALGORITHM_IDENTIFIER **supportedCMSTypes;/* OPTIONAL */ + CSSM_DATA *clientDHNonce; /* OPTIONAL */ +} KRB5_AuthPack; + +/* + * These are copied from keyTemplates.c in the libsecurity_asn1 project; + * they aren't public API. + */ + +/* AlgorithmIdentifier : CSSM_X509_ALGORITHM_IDENTIFIER */ +static const SecAsn1Template AlgorithmIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER) }, + { SEC_ASN1_OBJECT_ID, + offsetof(CSSM_X509_ALGORITHM_IDENTIFIER,algorithm), }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(CSSM_X509_ALGORITHM_IDENTIFIER,parameters), }, + { 0, } +}; + + +/* SubjectPublicKeyInfo : CSSM_X509_SUBJECT_PUBLIC_KEY_INFO */ +static const SecAsn1Template SubjectPublicKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) }, + { SEC_ASN1_INLINE, + offsetof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,algorithm), + AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,subjectPublicKey), }, + { 0, } +}; + +/* end of copied templates */ + +static const SecAsn1Template kSecAsn1SequenceOfAlgIdTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, AlgorithmIDTemplate } +}; + +static const SecAsn1Template KRB5_AuthPackTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_AuthPack) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_AuthPack,pkAuth), + KRB5_PKAuthenticatorTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | + SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 1, + offsetof(KRB5_AuthPack,pubKeyInfo), + SubjectPublicKeyInfoTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | + SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 2, + offsetof(KRB5_AuthPack,supportedCMSTypes), + kSecAsn1SequenceOfAlgIdTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | + SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 3, + offsetof(KRB5_AuthPack,clientDHNonce), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +/* + * Encode AuthPack, public key version (no Diffie-Hellman components). + */ +krb5_error_code krb5int_pkinit_auth_pack_encode( + krb5_timestamp kctime, + krb5_int32 cusec, /* microseconds */ + krb5_ui_4 nonce, + const krb5_checksum *pa_checksum, + const krb5int_algorithm_id *cms_types, /* optional */ + krb5_ui_4 num_cms_types, + krb5_data *auth_pack) /* mallocd and RETURNED */ +{ + KRB5_AuthPack localAuthPack; + SecAsn1CoderRef coder; + CSSM_DATA *cksum = &localAuthPack.pkAuth.paChecksum; + krb5_error_code ourRtn = 0; + CSSM_DATA ber = {0, NULL}; + OSStatus ortn; + char *timeStr = NULL; + + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&localAuthPack, 0, sizeof(localAuthPack)); + if(pkiKrbTimestampToStr(kctime, &timeStr)) { + ourRtn = -1; + goto errOut; + } + localAuthPack.pkAuth.kctime.Data = (uint8 *)timeStr; + localAuthPack.pkAuth.kctime.Length = strlen(timeStr); + if(pkiIntToData(cusec, &localAuthPack.pkAuth.cusec, coder)) { + ourRtn = ENOMEM; + goto errOut; + } + if(pkiIntToData(nonce, &localAuthPack.pkAuth.nonce, coder)) { + ourRtn = ENOMEM; + goto errOut; + } + cksum->Data = (uint8 *)pa_checksum->contents; + cksum->Length = pa_checksum->length; + + if((cms_types != NULL) && (num_cms_types != 0)) { + unsigned dex; + CSSM_X509_ALGORITHM_IDENTIFIER **algIds; + + /* build a NULL_terminated array of CSSM_X509_ALGORITHM_IDENTIFIERs */ + localAuthPack.supportedCMSTypes = (CSSM_X509_ALGORITHM_IDENTIFIER **) + SecAsn1Malloc(coder, + (num_cms_types + 1) * sizeof(CSSM_X509_ALGORITHM_IDENTIFIER *)); + algIds = localAuthPack.supportedCMSTypes; + for(dex=0; dexalgorithm, coder); + if(cms_types[dex].parameters.data != NULL) { + pkiKrb5DataToCssm(&cms_types[dex].parameters, + &algIds[dex]->parameters, coder); + } + else { + algIds[dex]->parameters.Data = NULL; + algIds[dex]->parameters.Length = 0; + } + } + algIds[num_cms_types] = NULL; + } + ortn = SecAsn1EncodeItem(coder, &localAuthPack, KRB5_AuthPackTemplate, &ber); + if(ortn) { + ourRtn = ENOMEM; + goto errOut; + } + + if(pkiCssmDataToKrb5Data(&ber, auth_pack)) { + ourRtn = ENOMEM; + } + else { + auth_pack->magic = KV5M_AUTHENTICATOR; + ourRtn = 0; + } +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +/* + * Decode AuthPack, public key version (no Diffie-Hellman components). + */ +krb5_error_code krb5int_pkinit_auth_pack_decode( + const krb5_data *auth_pack, /* DER encoded */ + krb5_timestamp *kctime, /* RETURNED */ + krb5_ui_4 *cusec, /* microseconds, RETURNED */ + krb5_ui_4 *nonce, /* RETURNED */ + krb5_checksum *pa_checksum, /* contents mallocd and RETURNED */ + krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ + krb5_ui_4 *num_cms_types) /* optionally RETURNED */ +{ + KRB5_AuthPack localAuthPack; + SecAsn1CoderRef coder; + CSSM_DATA der = {0, NULL}; + krb5_error_code ourRtn = 0; + CSSM_DATA *cksum = &localAuthPack.pkAuth.paChecksum; + + /* Decode --> localAuthPack */ + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + PKI_KRB_TO_CSSM_DATA(auth_pack, &der); + memset(&localAuthPack, 0, sizeof(localAuthPack)); + if(SecAsn1DecodeData(coder, &der, KRB5_AuthPackTemplate, &localAuthPack)) { + ourRtn = ASN1_BAD_FORMAT; + goto errOut; + } + + /* optionally Convert KRB5_AuthPack to caller's params */ + if(kctime) { + if((ourRtn = pkiTimeStrToKrbTimestamp((char *)localAuthPack.pkAuth.kctime.Data, + localAuthPack.pkAuth.kctime.Length, kctime))) { + goto errOut; + } + } + if(cusec) { + if((ourRtn = pkiDataToInt(&localAuthPack.pkAuth.cusec, (krb5_int32 *)cusec))) { + goto errOut; + } + } + if(nonce) { + if((ourRtn = pkiDataToInt(&localAuthPack.pkAuth.nonce, (krb5_int32 *)nonce))) { + goto errOut; + } + } + if(pa_checksum) { + if(cksum->Length == 0) { + /* This is the unique error for "no paChecksum" */ + ourRtn = KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; + goto errOut; + } + else { + pa_checksum->contents = (krb5_octet *)malloc(cksum->Length); + if(pa_checksum->contents == NULL) { + ourRtn = ENOMEM; + goto errOut; + } + pa_checksum->length = cksum->Length; + memmove(pa_checksum->contents, cksum->Data, pa_checksum->length); + pa_checksum->magic = KV5M_CHECKSUM; + /* This used to be encoded with the checksum but no more... */ + pa_checksum->checksum_type = CKSUMTYPE_NIST_SHA; + } + } + if(cms_types) { + if(localAuthPack.supportedCMSTypes == NULL) { + *cms_types = NULL; + *num_cms_types = 0; + } + else { + /* + * Convert NULL-terminated array of CSSM-style algIds to + * krb5int_algorithm_ids. + */ + unsigned dex; + unsigned num_types = 0; + CSSM_X509_ALGORITHM_IDENTIFIER **alg_ids; + krb5int_algorithm_id *kalg_ids; + + for(alg_ids=localAuthPack.supportedCMSTypes; + *alg_ids; + alg_ids++) { + num_types++; + } + *cms_types = kalg_ids = (krb5int_algorithm_id *)calloc(num_types, + sizeof(krb5int_algorithm_id)); + *num_cms_types = num_types; + alg_ids = localAuthPack.supportedCMSTypes; + for(dex=0; dexalgorithm.Data) { + pkiCssmDataToKrb5Data(&alg_ids[dex]->algorithm, + &kalg_ids[dex].algorithm); + } + if(alg_ids[dex]->parameters.Data) { + pkiCssmDataToKrb5Data(&alg_ids[dex]->parameters, + &kalg_ids[dex].parameters); + } + } + } + } + ourRtn = 0; +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +#pragma mark ----- IssuerAndSerialNumber ----- + +/* + * Issuer/serial number - specify issuer as ASN_ANY because we can get it from + * CL in DER-encoded state. + */ +typedef struct { + CSSM_DATA derIssuer; + CSSM_DATA serialNumber; +} KRB5_IssuerAndSerial; + +static const SecAsn1Template KRB5_IssuerAndSerialTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_IssuerAndSerial) }, + { SEC_ASN1_ANY, offsetof(KRB5_IssuerAndSerial, derIssuer) }, + { SEC_ASN1_INTEGER, offsetof(KRB5_IssuerAndSerial, serialNumber) }, + { 0 } +}; + +/* + * Given DER-encoded issuer and serial number, create an encoded + * IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_issuer_serial_encode( + const krb5_data *issuer, /* DER encoded */ + const krb5_data *serial_num, + krb5_data *issuer_and_serial) /* content mallocd and RETURNED */ +{ + KRB5_IssuerAndSerial issuerSerial; + SecAsn1CoderRef coder; + CSSM_DATA ber = {0, NULL}; + OSStatus ortn; + + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + PKI_KRB_TO_CSSM_DATA(issuer, &issuerSerial.derIssuer); + PKI_KRB_TO_CSSM_DATA(serial_num, &issuerSerial.serialNumber); + ortn = SecAsn1EncodeItem(coder, &issuerSerial, KRB5_IssuerAndSerialTemplate, &ber); + if(ortn) { + ortn = ENOMEM; + goto errOut; + } + ortn = pkiCssmDataToKrb5Data(&ber, issuer_and_serial); +errOut: + SecAsn1CoderRelease(coder); + return ortn; +} + +/* + * Decode IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_issuer_serial_decode( + const krb5_data *issuer_and_serial, /* DER encoded */ + krb5_data *issuer, /* DER encoded, RETURNED */ + krb5_data *serial_num) /* RETURNED */ +{ + KRB5_IssuerAndSerial issuerSerial; + SecAsn1CoderRef coder; + CSSM_DATA der = {issuer_and_serial->length, (uint8 *)issuer_and_serial->data}; + krb5_error_code ourRtn = 0; + + /* Decode --> issuerSerial */ + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&issuerSerial, 0, sizeof(issuerSerial)); + if(SecAsn1DecodeData(coder, &der, KRB5_IssuerAndSerialTemplate, &issuerSerial)) { + ourRtn = ASN1_BAD_FORMAT; + goto errOut; + } + + /* Convert KRB5_IssuerAndSerial to caller's params */ + if((ourRtn = pkiCssmDataToKrb5Data(&issuerSerial.derIssuer, issuer))) { + goto errOut; + } + if((ourRtn = pkiCssmDataToKrb5Data(&issuerSerial.serialNumber, serial_num))) { + ourRtn = ENOMEM; + goto errOut; + } + +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +#pragma mark ----- ExternalPrincipalIdentifier ----- + +/* + * Shown here for completeness; this module only implements the + * issuerAndSerialNumber option. + */ +typedef struct { + CSSM_DATA subjectName; /* [0] IMPLICIT OCTET STRING OPTIONAL */ + /* contents = encoded Name */ + CSSM_DATA issuerAndSerialNumber; /* [1] IMPLICIT OCTET STRING OPTIONAL */ + /* contents = encoded Issuer&Serial */ + CSSM_DATA subjectKeyIdentifier; /* [2] IMPLICIT OCTET STRING OPTIONAL */ + /* contents = encoded subjectKeyIdentifier extension */ +} KRB5_ExternalPrincipalIdentifier; + +static const SecAsn1Template KRB5_ExternalPrincipalIdentifierTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_ExternalPrincipalIdentifier) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 0, + offsetof(KRB5_ExternalPrincipalIdentifier, subjectName), + kSecAsn1OctetStringTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 1, + offsetof(KRB5_ExternalPrincipalIdentifier, issuerAndSerialNumber), + kSecAsn1OctetStringTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 2, + offsetof(KRB5_ExternalPrincipalIdentifier, subjectKeyIdentifier), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +static const SecAsn1Template KRB5_SequenceOfExternalPrincipalIdentifierTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, KRB5_ExternalPrincipalIdentifierTemplate } +}; + +#pragma mark ----- PA-PK-AS-REQ ----- + +/* + * Top-level PA-PK-AS-REQ. All fields except for trusted_CAs are pre-encoded + * before we encode this and are still DER-encoded after we decode. + * The signedAuthPack and kdcPkId fields are wrapped in OCTET STRINGs + * during encode; we strip off the OCTET STRING wrappers during decode. + */ +typedef struct { + CSSM_DATA signedAuthPack; /* ContentInfo, SignedData */ + /* Content is KRB5_AuthPack */ + KRB5_ExternalPrincipalIdentifier + **trusted_CAs; /* optional */ + CSSM_DATA kdcPkId; /* optional */ +} KRB5_PA_PK_AS_REQ; + +static const SecAsn1Template KRB5_PA_PK_AS_REQTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PA_PK_AS_REQ) }, + { SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(KRB5_PA_PK_AS_REQ, signedAuthPack), + kSecAsn1OctetStringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_PA_PK_AS_REQ, trusted_CAs), + KRB5_SequenceOfExternalPrincipalIdentifierTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(KRB5_PA_PK_AS_REQ, kdcPkId), + kSecAsn1AnyTemplate }, + { 0 } +}; + +/* + * Top-level encode for PA-PK-AS-REQ. + */ +krb5_error_code krb5int_pkinit_pa_pk_as_req_encode( + const krb5_data *signed_auth_pack, /* DER encoded ContentInfo */ + const krb5_data *trusted_CAs, /* optional: trustedCertifiers. Contents are + * DER-encoded issuer/serialNumbers. */ + krb5_ui_4 num_trusted_CAs, + const krb5_data *kdc_cert, /* optional kdcPkId, DER encoded issuer/serial */ + krb5_data *pa_pk_as_req) /* mallocd and RETURNED */ +{ + KRB5_PA_PK_AS_REQ req; + SecAsn1CoderRef coder; + CSSM_DATA ber = {0, NULL}; + OSStatus ortn; + unsigned dex; + + assert(signed_auth_pack != NULL); + assert(pa_pk_as_req != NULL); + + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + + /* krb5_data ==> CSSM format */ + + memset(&req, 0, sizeof(req)); + PKI_KRB_TO_CSSM_DATA(signed_auth_pack, &req.signedAuthPack); + if(num_trusted_CAs) { + /* + * Set up a NULL-terminated array of KRB5_ExternalPrincipalIdentifier + * pointers. We malloc the actual KRB5_ExternalPrincipalIdentifiers as + * a contiguous array; it's in temp SecAsn1CoderRef memory. The referents + * are just dropped in from the caller's krb5_datas. + */ + KRB5_ExternalPrincipalIdentifier *cas = + (KRB5_ExternalPrincipalIdentifier *)SecAsn1Malloc(coder, + num_trusted_CAs * sizeof(KRB5_ExternalPrincipalIdentifier)); + req.trusted_CAs = + (KRB5_ExternalPrincipalIdentifier **) + pkiNssNullArray(num_trusted_CAs, coder); + for(dex=0; dex KRB5_PA_PK_AS_REQ */ + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + PKI_KRB_TO_CSSM_DATA(pa_pk_as_req, &der); + memset(&asReq, 0, sizeof(asReq)); + if(SecAsn1DecodeData(coder, &der, KRB5_PA_PK_AS_REQTemplate, &asReq)) { + ourRtn = ASN1_BAD_FORMAT; + goto errOut; + } + + /* Convert decoded results to caller's args; each is optional */ + if(signed_auth_pack != NULL) { + if((ourRtn = pkiCssmDataToKrb5Data(&asReq.signedAuthPack, signed_auth_pack))) { + goto errOut; + } + } + if(asReq.trusted_CAs && (trusted_CAs != NULL)) { + /* NULL-terminated array of CSSM_DATA ptrs */ + unsigned numCas = pkiNssArraySize((const void **)asReq.trusted_CAs); + unsigned dex; + krb5_data *kdcCas; + + kdcCas = (krb5_data *)malloc(sizeof(krb5_data) * numCas); + if(kdcCas == NULL) { + ourRtn = ENOMEM; + goto errOut; + } + for(dex=0; dexissuerAndSerialNumber.Data) { + /* the only variant we support */ + pkiCssmDataToKrb5Data(&epi->issuerAndSerialNumber, &kdcCas[dex]); + } + } + *trusted_CAs = kdcCas; + *num_trusted_CAs = numCas; + } + if(asReq.kdcPkId.Data && kdc_cert) { + if((ourRtn = pkiCssmDataToKrb5Data(&asReq.kdcPkId, kdc_cert))) { + goto errOut; + } + } +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +#pragma mark ====== begin PA-PK-AS-REP components ====== + +typedef struct { + CSSM_DATA subjectPublicKey; /* BIT STRING */ + CSSM_DATA nonce; /* from KRB5_PKAuthenticator.nonce */ + CSSM_DATA *expiration; /* optional UTC time */ +} KRB5_KDC_DHKeyInfo; + +typedef struct { + CSSM_DATA keyType; + CSSM_DATA keyValue; +} KRB5_EncryptionKey; + +static const SecAsn1Template KRB5_EncryptionKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_EncryptionKey) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_EncryptionKey, keyType), + kSecAsn1IntegerTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_EncryptionKey, keyValue), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +#pragma mark ----- Checksum ----- + +typedef struct { + CSSM_DATA checksumType; + CSSM_DATA checksum; +} KRB5_Checksum; + +static const SecAsn1Template KRB5_ChecksumTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_Checksum) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_Checksum,checksumType), + kSecAsn1IntegerTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_Checksum,checksum), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +typedef struct { + KRB5_EncryptionKey encryptionKey; + KRB5_Checksum asChecksum; +} KRB5_ReplyKeyPack; + +static const SecAsn1Template KRB5_ReplyKeyPackTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_ReplyKeyPack) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_ReplyKeyPack, encryptionKey), + KRB5_EncryptionKeyTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_ReplyKeyPack,asChecksum), + KRB5_ChecksumTemplate }, + { 0 } +}; + +/* + * Encode a ReplyKeyPack. The result is used as the Content of a SignedData. + */ +krb5_error_code krb5int_pkinit_reply_key_pack_encode( + const krb5_keyblock *key_block, + const krb5_checksum *checksum, + krb5_data *reply_key_pack) /* mallocd and RETURNED */ +{ + KRB5_ReplyKeyPack repKeyPack; + SecAsn1CoderRef coder; + krb5_error_code ourRtn = 0; + CSSM_DATA der = {0, NULL}; + OSStatus ortn; + KRB5_EncryptionKey *encryptKey = &repKeyPack.encryptionKey; + KRB5_Checksum *cksum = &repKeyPack.asChecksum; + + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&repKeyPack, 0, sizeof(repKeyPack)); + + if((ourRtn = pkiIntToData(key_block->enctype, &encryptKey->keyType, coder))) { + goto errOut; + } + encryptKey->keyValue.Length = key_block->length, + encryptKey->keyValue.Data = (uint8 *)key_block->contents; + + if((ourRtn = pkiIntToData(checksum->checksum_type, &cksum->checksumType, coder))) { + goto errOut; + } + cksum->checksum.Data = (uint8 *)checksum->contents; + cksum->checksum.Length = checksum->length; + + ortn = SecAsn1EncodeItem(coder, &repKeyPack, KRB5_ReplyKeyPackTemplate, &der); + if(ortn) { + ourRtn = ENOMEM; + goto errOut; + } + ourRtn = pkiCssmDataToKrb5Data(&der, reply_key_pack); +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +/* + * Decode a ReplyKeyPack. + */ +krb5_error_code krb5int_pkinit_reply_key_pack_decode( + const krb5_data *reply_key_pack, + krb5_keyblock *key_block, /* RETURNED */ + krb5_checksum *checksum) /* contents mallocd and RETURNED */ +{ + KRB5_ReplyKeyPack repKeyPack; + SecAsn1CoderRef coder; + krb5_error_code ourRtn = 0; + KRB5_EncryptionKey *encryptKey = &repKeyPack.encryptionKey; + CSSM_DATA der = {reply_key_pack->length, (uint8 *)reply_key_pack->data}; + krb5_data tmpData; + KRB5_Checksum *cksum = &repKeyPack.asChecksum; + + /* Decode --> KRB5_ReplyKeyPack */ + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&repKeyPack, 0, sizeof(repKeyPack)); + if(SecAsn1DecodeData(coder, &der, KRB5_ReplyKeyPackTemplate, &repKeyPack)) { + ourRtn = ASN1_BAD_FORMAT; + goto errOut; + } + + if((ourRtn = pkiDataToInt(&encryptKey->keyType, (krb5_int32 *)&key_block->enctype))) { + goto errOut; + } + if((ourRtn = pkiCssmDataToKrb5Data(&encryptKey->keyValue, &tmpData))) { + goto errOut; + } + key_block->contents = (krb5_octet *)tmpData.data; + key_block->length = tmpData.length; + + if((ourRtn = pkiDataToInt(&cksum->checksumType, &checksum->checksum_type))) { + goto errOut; + } + checksum->contents = (krb5_octet *)malloc(cksum->checksum.Length); + if(checksum->contents == NULL) { + ourRtn = ENOMEM; + goto errOut; + } + checksum->length = cksum->checksum.Length; + memmove(checksum->contents, cksum->checksum.Data, checksum->length); + checksum->magic = KV5M_CHECKSUM; + +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + + +#pragma mark ----- KRB5_PA_PK_AS_REP ----- +/* + * Top-level PA-PK-AS-REP. Exactly one of the optional fields must be present. + */ +typedef struct { + CSSM_DATA *dhSignedData; /* ContentInfo, SignedData */ + /* Content is KRB5_KDC_DHKeyInfo */ + CSSM_DATA *encKeyPack; /* ContentInfo, SignedData */ + /* Content is ReplyKeyPack */ +} KRB5_PA_PK_AS_REP; + +static const SecAsn1Template KRB5_PA_PK_AS_REPTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PA_PK_AS_REP) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | + SEC_ASN1_EXPLICIT | 0, + offsetof(KRB5_PA_PK_AS_REP, dhSignedData), + kSecAsn1PointerToAnyTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | + SEC_ASN1_EXPLICIT | 1, + offsetof(KRB5_PA_PK_AS_REP, encKeyPack), + kSecAsn1PointerToAnyTemplate }, + { 0 } +}; + +/* + * Encode a KRB5_PA_PK_AS_REP. + */ +krb5_error_code krb5int_pkinit_pa_pk_as_rep_encode( + const krb5_data *dh_signed_data, + const krb5_data *enc_key_pack, + krb5_data *pa_pk_as_rep) /* mallocd and RETURNED */ +{ + KRB5_PA_PK_AS_REP asRep; + SecAsn1CoderRef coder; + krb5_error_code ourRtn = 0; + CSSM_DATA der = {0, NULL}; + OSStatus ortn; + CSSM_DATA dhSignedData; + CSSM_DATA encKeyPack; + + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&asRep, 0, sizeof(asRep)); + if(dh_signed_data) { + PKI_KRB_TO_CSSM_DATA(dh_signed_data, &dhSignedData); + asRep.dhSignedData = &dhSignedData; + } + if(enc_key_pack) { + PKI_KRB_TO_CSSM_DATA(enc_key_pack, &encKeyPack); + asRep.encKeyPack = &encKeyPack; + } + + ortn = SecAsn1EncodeItem(coder, &asRep, KRB5_PA_PK_AS_REPTemplate, &der); + if(ortn) { + ourRtn = ENOMEM; + goto errOut; + } + ourRtn = pkiCssmDataToKrb5Data(&der, pa_pk_as_rep); + +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +/* + * Decode a KRB5_PA_PK_AS_REP. + */ +krb5_error_code krb5int_pkinit_pa_pk_as_rep_decode( + const krb5_data *pa_pk_as_rep, + krb5_data *dh_signed_data, + krb5_data *enc_key_pack) +{ + KRB5_PA_PK_AS_REP asRep; + SecAsn1CoderRef coder; + CSSM_DATA der = {pa_pk_as_rep->length, (uint8 *)pa_pk_as_rep->data}; + krb5_error_code ourRtn = 0; + + /* Decode --> KRB5_PA_PK_AS_REP */ + if(SecAsn1CoderCreate(&coder)) { + return ENOMEM; + } + memset(&asRep, 0, sizeof(asRep)); + if(SecAsn1DecodeData(coder, &der, KRB5_PA_PK_AS_REPTemplate, &asRep)) { + ourRtn = ASN1_BAD_FORMAT; + goto errOut; + } + + if(asRep.dhSignedData) { + if((ourRtn = pkiCssmDataToKrb5Data(asRep.dhSignedData, dh_signed_data))) { + goto errOut; + } + } + if(asRep.encKeyPack) { + ourRtn = pkiCssmDataToKrb5Data(asRep.encKeyPack, enc_key_pack); + } + +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +#pragma mark ====== General utilities ====== + +/* + * Given a DER encoded certificate, obtain the associated IssuerAndSerialNumber. + */ +krb5_error_code krb5int_pkinit_get_issuer_serial( + const krb5_data *cert, + krb5_data *issuer_and_serial) +{ + CSSM_HANDLE cacheHand = 0; + CSSM_RETURN crtn = CSSM_OK; + CSSM_DATA certData = { cert->length, (uint8 *)cert->data }; + CSSM_HANDLE resultHand = 0; + CSSM_DATA_PTR derIssuer = NULL; + CSSM_DATA_PTR serial; + krb5_data krb_serial; + krb5_data krb_issuer; + uint32 numFields; + krb5_error_code ourRtn = 0; + + CSSM_CL_HANDLE clHand = pkiClStartup(); + if(clHand == 0) { + return CSSMERR_CSSM_ADDIN_LOAD_FAILED; + } + /* subsequent errors to errOut: */ + + crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand); + if(crtn) { + pkiCssmErr("CSSM_CL_CertCache", crtn); + ourRtn = ASN1_PARSE_ERROR; + goto errOut; + } + + /* obtain the two fields; issuer is DER encoded */ + crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, + &CSSMOID_X509V1IssuerNameStd, &resultHand, &numFields, &derIssuer); + if(crtn) { + pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(issuer)", crtn); + ourRtn = ASN1_PARSE_ERROR; + goto errOut; + } + crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, + &CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &serial); + if(crtn) { + pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(serial)", crtn); + ourRtn = ASN1_PARSE_ERROR; + goto errOut; + } + PKI_CSSM_TO_KRB_DATA(derIssuer, &krb_issuer); + PKI_CSSM_TO_KRB_DATA(serial, &krb_serial); + ourRtn = krb5int_pkinit_issuer_serial_encode(&krb_issuer, &krb_serial, issuer_and_serial); + +errOut: + if(derIssuer) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerNameStd, derIssuer); + } + if(serial) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, serial); + } + if(cacheHand) { + CSSM_CL_CertAbortCache(clHand, cacheHand); + } + if(clHand) { + pkiClDetachUnload(clHand); + } + return ourRtn; +} + +#endif /* APPLE_PKINIT */ diff --git a/krb5-1-7/src/lib/krb5/krb/pkinit_apple_cert_store.c b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_cert_store.c new file mode 100644 index 000000000..449f1cc99 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_cert_store.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_cert_store.c - PKINIT certificate storage/retrieval utilities, + * MAC OS X version + * + * Created 26 May 2004 by Doug Mitchell at Apple. + */ + +#if APPLE_PKINIT + +#include "pkinit_cert_store.h" +#include "pkinit_asn1.h" +#include "pkinit_apple_utils.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Client cert info is stored in preferences with this following parameters: + * + * key = kPkinitClientCertKey + * appID = kPkinitClientCertApp + * username = kCFPreferencesCurrentUser + * hostname = kCFPreferencesAnyHost + * + * The stored property list is a CFDictionary. Keys in the dictionary are + * principal names (e.g. foobar@REALM.LOCAL). + * + * Values in the dictionary are raw data containing the DER-encoded issuer and + * serial number of the certificate. + * + * When obtaining a PKINIT cert, if an entry in the CFDictionary for the specified + * principal is not found, the entry for the default will be used if it's there. + */ + +/* + * NOTE: ANSI C code requires an Apple-Custom -fconstant-cfstrings CFLAGS to + * use CFSTR in a const declaration so we just declare the C strings here. + */ +#define kPkinitClientCertKey "KRBClientCert" +#define kPkinitClientCertApp "edu.mit.Kerberos.pkinit" + +/* + * KDC cert stored in this keychain. It's linked to systemkeychain so that if + * a root process tries to unlock it, it auto-unlocks. + */ +#define KDC_KEYCHAIN "/var/db/krb5kdc/kdc.keychain" + +/* + * Given a certificate, obtain the DER-encoded issuer and serial number. Result + * is mallocd and must be freed by caller. + */ +static OSStatus pkinit_get_cert_issuer_sn( + SecCertificateRef certRef, + CSSM_DATA *issuerSerial) /* mallocd and RETURNED */ +{ + OSStatus ortn; + CSSM_DATA certData; + krb5_data INIT_KDATA(issuerSerialKrb); + krb5_data certDataKrb; + krb5_error_code krtn; + + assert(certRef != NULL); + assert(issuerSerial != NULL); + + ortn = SecCertificateGetData(certRef, &certData); + if(ortn) { + pkiCssmErr("SecCertificateGetData", ortn); + return ortn; + } + PKI_CSSM_TO_KRB_DATA(&certData, &certDataKrb); + krtn = krb5int_pkinit_get_issuer_serial(&certDataKrb, &issuerSerialKrb); + if(krtn) { + return CSSMERR_CL_INVALID_DATA; + } + PKI_KRB_TO_CSSM_DATA(&issuerSerialKrb, issuerSerial); + return noErr; +} + +/* + * Determine if specified identity's cert's issuer and serial number match the + * provided issuer and serial number. Returns nonzero on match, else returns zero. + */ +static int pkinit_issuer_sn_match( + SecIdentityRef idRef, + const CSSM_DATA *matchIssuerSerial) +{ + OSStatus ortn; + SecCertificateRef certRef = NULL; + CSSM_DATA INIT_CDATA(certIssuerSerial); + int ourRtn = 0; + + assert(idRef != NULL); + assert(matchIssuerSerial != NULL); + + /* Get this cert's issuer/serial number */ + ortn = SecIdentityCopyCertificate(idRef, &certRef); + if(ortn) { + pkiCssmErr("SecIdentityCopyCertificate", ortn); + return 0; + } + /* subsequent errors to errOut: */ + ortn = pkinit_get_cert_issuer_sn(certRef, &certIssuerSerial); + if(ortn) { + pkiCssmErr("SecIdentityCopyCertificate", ortn); + goto errOut; + } + ourRtn = pkiCompareCssmData(matchIssuerSerial, &certIssuerSerial) ? 1 : 0; +errOut: + if(certRef != NULL) { + CFRelease(certRef); + } + if(certIssuerSerial.Data != NULL) { + free(certIssuerSerial.Data); + } + return ourRtn; +} + +/* + * Search specified keychain/array/NULL (NULL meaning the default search list) for + * an Identity matching specified key usage and optional Issuer/Serial number. + * If issuer/serial is specified and no identities match, or if no identities found + * matching specified Key usage, errSecItemNotFound is returned. + * + * Caller must CFRelease a non-NULL returned idRef. + */ +static OSStatus pkinit_search_ident( + CFTypeRef keychainOrArray, + CSSM_KEYUSE keyUsage, + const CSSM_DATA *issuerSerial, /* optional */ + SecIdentityRef *foundId) /* RETURNED */ +{ + OSStatus ortn; + SecIdentityRef idRef = NULL; + SecIdentitySearchRef srchRef = NULL; + + ortn = SecIdentitySearchCreate(keychainOrArray, keyUsage, &srchRef); + if(ortn) { + pkiCssmErr("SecIdentitySearchCreate", ortn); + return ortn; + } + do { + ortn = SecIdentitySearchCopyNext(srchRef, &idRef); + if(ortn != noErr) { + break; + } + if(issuerSerial == NULL) { + /* no match needed, we're done - this is the KDC cert case */ + break; + } + else if(pkinit_issuer_sn_match(idRef, issuerSerial)) { + /* match, we're done */ + break; + } + /* finished with this one */ + CFRelease(idRef); + idRef = NULL; + } while(ortn == noErr); + + CFRelease(srchRef); + if(idRef == NULL) { + return errSecItemNotFound; + } + else { + *foundId = idRef; + return noErr; + } +} + +/* + * In Mac OS terms, get the keychain on which a given identity resides. + */ +static krb5_error_code pkinit_cert_to_db( + krb5_pkinit_signing_cert_t idRef, + krb5_pkinit_cert_db_t *dbRef) +{ + SecKeychainRef kcRef = NULL; + SecKeyRef keyRef = NULL; + OSStatus ortn; + + /* that's an identity - get the associated key's keychain */ + ortn = SecIdentityCopyPrivateKey((SecIdentityRef)idRef, &keyRef); + if(ortn) { + pkiCssmErr("SecIdentityCopyPrivateKey", ortn); + return ortn; + } + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); + if(ortn) { + pkiCssmErr("SecKeychainItemCopyKeychain", ortn); + } + else { + *dbRef = (krb5_pkinit_cert_db_t)kcRef; + } + CFRelease(keyRef); + return ortn; +} + +/* + * Obtain the CFDictionary representing this user's PKINIT client cert prefs, if it + * exists. Returns noErr or errSecItemNotFound as appropriate. + */ +static OSStatus pkinit_get_pref_dict( + CFDictionaryRef *dict) +{ + CFDictionaryRef theDict; + theDict = (CFDictionaryRef)CFPreferencesCopyValue(CFSTR(kPkinitClientCertKey), + CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + if(theDict == NULL) { + pkiDebug("pkinit_get_pref_dict: no kPkinitClientCertKey\n"); + return errSecItemNotFound; + } + if(CFGetTypeID(theDict) != CFDictionaryGetTypeID()) { + pkiDebug("pkinit_get_pref_dict: bad kPkinitClientCertKey pref\n"); + CFRelease(theDict); + return errSecItemNotFound; + } + *dict = theDict; + return noErr; +} + +#pragma mark --- Public client side functions --- + +/* + * Obtain signing cert for specified principal. On successful return, + * caller must eventually release the cert with krb5_pkinit_release_cert(). + */ +krb5_error_code krb5_pkinit_get_client_cert( + const char *principal, /* full principal string */ + krb5_pkinit_signing_cert_t *client_cert) +{ + CFDataRef issuerSerial = NULL; + CSSM_DATA issuerSerialData; + SecIdentityRef idRef = NULL; + OSStatus ortn; + CFDictionaryRef theDict = NULL; + CFStringRef cfPrinc = NULL; + krb5_error_code ourRtn = 0; + + if(principal == NULL) { + return KRB5_PRINC_NOMATCH; + } + + /* Is there a stored preference for PKINIT certs for this user? */ + ortn = pkinit_get_pref_dict(&theDict); + if(ortn) { + return KRB5_PRINC_NOMATCH; + } + + /* Entry in the dictionary for specified principal? */ + cfPrinc = CFStringCreateWithCString(NULL, principal, + kCFStringEncodingASCII); + issuerSerial = (CFDataRef)CFDictionaryGetValue(theDict, cfPrinc); + CFRelease(cfPrinc); + if(issuerSerial == NULL) { + pkiDebug("krb5_pkinit_get_client_cert: no identity found\n"); + ourRtn = KRB5_PRINC_NOMATCH; + goto errOut; + } + if(CFGetTypeID(issuerSerial) != CFDataGetTypeID()) { + pkiDebug("krb5_pkinit_get_client_cert: bad kPkinitClientCertKey value\n"); + ourRtn = KRB5_PRINC_NOMATCH; + goto errOut; + } + + issuerSerialData.Data = (uint8 *)CFDataGetBytePtr(issuerSerial); + issuerSerialData.Length = CFDataGetLength(issuerSerial); + + /* find a cert with that issuer/serial number in default search list */ + ortn = pkinit_search_ident(NULL, CSSM_KEYUSE_SIGN | CSSM_KEYUSE_ENCRYPT, + &issuerSerialData, &idRef); + if(ortn) { + pkiDebug("krb5_pkinit_get_client_cert: no identity found!\n"); + pkiCssmErr("pkinit_search_ident", ortn); + ourRtn = KRB5_PRINC_NOMATCH; + } + else { + *client_cert = (krb5_pkinit_signing_cert_t)idRef; + } +errOut: + if(theDict) { + CFRelease(theDict); + } + return ourRtn; +} + +/* + * Determine if the specified client has a signing cert. Returns TRUE + * if so, else returns FALSE. + */ +krb5_boolean krb5_pkinit_have_client_cert( + const char *principal) /* full principal string */ +{ + krb5_pkinit_signing_cert_t signing_cert = NULL; + krb5_error_code krtn; + + krtn = krb5_pkinit_get_client_cert(principal, &signing_cert); + if(krtn) { + return FALSE; + } + if(signing_cert != NULL) { + krb5_pkinit_release_cert(signing_cert); + return TRUE; + } + else { + return FALSE; + } +} + +/* + * Store the specified certificate (or, more likely, some platform-dependent + * reference to it) as the specified principal's signing certificate. Passing + * in NULL for the client_cert has the effect of deleting the relevant entry + * in the cert storage. + */ +krb5_error_code krb5_pkinit_set_client_cert_from_signing_cert( + const char *principal, /* full principal string */ + krb5_pkinit_signing_cert_t client_cert) +{ + SecIdentityRef idRef = (SecIdentityRef)client_cert; + SecCertificateRef certRef = NULL; + OSStatus ortn; + krb5_error_code ourRtn = 0; + + if (NULL != idRef) { + if (CFGetTypeID(idRef) != SecIdentityGetTypeID()) { + ourRtn = KRB5KRB_ERR_GENERIC; + goto fin; + } + /* Get the cert */ + ortn = SecIdentityCopyCertificate(idRef, &certRef); + if (ortn) { + pkiCssmErr("SecIdentityCopyCertificate", ortn); + ourRtn = KRB5KRB_ERR_GENERIC; + goto fin; + } + } + ourRtn = krb5_pkinit_set_client_cert(principal, (krb5_pkinit_cert_t)certRef); +fin: + if (certRef) + CFRelease(certRef); + return ourRtn; +} + + +/* + * Store the specified certificate (or, more likely, some platform-dependent + * reference to it) as the specified principal's certificate. Passing + * in NULL for the client_cert has the effect of deleting the relevant entry + * in the cert storage. + */ +krb5_error_code krb5_pkinit_set_client_cert( + const char *principal, /* full principal string */ + krb5_pkinit_cert_t client_cert) +{ + SecCertificateRef certRef = (SecCertificateRef)client_cert; + OSStatus ortn; + CSSM_DATA issuerSerial = {0, NULL}; + CFDataRef cfIssuerSerial = NULL; + CFDictionaryRef existDict = NULL; + CFMutableDictionaryRef newDict = NULL; + CFStringRef keyStr = NULL; + krb5_error_code ourRtn = 0; + + if(certRef != NULL) { + if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { + return KRB5KRB_ERR_GENERIC; + } + + /* Cook up DER-encoded issuer/serial number */ + ortn = pkinit_get_cert_issuer_sn(certRef, &issuerSerial); + if(ortn) { + ourRtn = KRB5KRB_ERR_GENERIC; + goto errOut; + } + } + + /* + * Obtain the existing pref for kPkinitClientCertKey as a CFDictionary, or + * cook up a new one. + */ + ortn = pkinit_get_pref_dict(&existDict); + if(ortn == noErr) { + /* dup to a mutable dictionary */ + newDict = CFDictionaryCreateMutableCopy(NULL, 0, existDict); + } + else { + if(certRef == NULL) { + /* no existing entry, nothing to delete, we're done */ + return 0; + } + newDict = CFDictionaryCreateMutable(NULL, 0, + &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + if(newDict == NULL) { + ourRtn = ENOMEM; + goto errOut; + } + + /* issuer / serial number ==> that dictionary */ + keyStr = CFStringCreateWithCString(NULL, principal, kCFStringEncodingASCII); + if(certRef == NULL) { + CFDictionaryRemoveValue(newDict, keyStr); + } + else { + cfIssuerSerial = CFDataCreate(NULL, issuerSerial.Data, issuerSerial.Length); + CFDictionarySetValue(newDict, keyStr, cfIssuerSerial); + } + + /* dictionary ==> prefs */ + CFPreferencesSetValue(CFSTR(kPkinitClientCertKey), newDict, + CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + if(CFPreferencesSynchronize(CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, + kCFPreferencesAnyHost)) { + ourRtn = 0; + } + else { + ourRtn = EACCES; /* any better ideas? */ + } +errOut: + if(cfIssuerSerial) { + CFRelease(cfIssuerSerial); + } + if(issuerSerial.Data) { + free(issuerSerial.Data); + } + if(existDict) { + CFRelease(existDict); + } + if(newDict) { + CFRelease(newDict); + } + if(keyStr) { + CFRelease(keyStr); + } + return ourRtn; +} + +/* + * Obtain a reference to the client's cert database. Specify either principal + * name or client_cert as obtained from krb5_pkinit_get_client_cert(). + */ +krb5_error_code krb5_pkinit_get_client_cert_db( + const char *principal, /* full principal string */ + krb5_pkinit_signing_cert_t client_cert, /* optional, from krb5_pkinit_get_client_cert() */ + krb5_pkinit_cert_db_t *client_cert_db)/* RETURNED */ +{ + krb5_error_code krtn; + krb5_pkinit_signing_cert_t local_cert; + + assert((client_cert != NULL) || (principal != NULL)); + if(client_cert == NULL) { + /* caller didn't provide, look it up */ + krtn = krb5_pkinit_get_client_cert(principal, &local_cert); + if(krtn) { + return krtn; + } + } + else { + /* easy case */ + local_cert = client_cert; + } + krtn = pkinit_cert_to_db(local_cert, client_cert_db); + if(client_cert == NULL) { + krb5_pkinit_release_cert(local_cert); + } + return krtn; +} + +#pragma mark --- Public server side functions --- + +/* + * Obtain the KDC signing cert, with optional CA and specific cert specifiers. + * CAs and cert specifiers are in the form of DER-encoded issuerAndSerialNumbers. + * + * The client_spec argument is typically provided by the client as kdcPkId. + */ +krb5_error_code krb5_pkinit_get_kdc_cert( + krb5_ui_4 num_trusted_CAs, /* sizeof *trusted_CAs */ + krb5_data *trusted_CAs, /* optional */ + krb5_data *client_spec, /* optional */ + krb5_pkinit_signing_cert_t *kdc_cert) +{ + SecIdentityRef idRef = NULL; + OSStatus ortn; + krb5_error_code ourRtn = 0; + + /* OS X: trusted_CAs and client_spec ignored */ + + ortn = SecIdentityCopySystemIdentity(kSecIdentityDomainKerberosKDC, + &idRef, NULL); + if(ortn) { + pkiCssmErr("SecIdentityCopySystemIdentity", ortn); + return KRB5_PRINC_NOMATCH; + } + *kdc_cert = (krb5_pkinit_signing_cert_t)idRef; + return ourRtn; +} + +/* + * Obtain a reference to the KDC's cert database. + */ +krb5_error_code krb5_pkinit_get_kdc_cert_db( + krb5_pkinit_cert_db_t *kdc_cert_db) +{ + krb5_pkinit_signing_cert_t kdcCert = NULL; + krb5_error_code krtn; + + krtn = krb5_pkinit_get_kdc_cert(0, NULL, NULL, &kdcCert); + if(krtn) { + return krtn; + } + krtn = pkinit_cert_to_db(kdcCert, kdc_cert_db); + krb5_pkinit_release_cert(kdcCert); + return krtn; +} + +/* + * Release certificate references obtained via krb5_pkinit_get_client_cert() and + * krb5_pkinit_get_kdc_cert(). + */ +void krb5_pkinit_release_cert( + krb5_pkinit_signing_cert_t cert) +{ + if(cert == NULL) { + return; + } + CFRelease((CFTypeRef)cert); +} + +/* + * Release database references obtained via krb5_pkinit_get_client_cert_db() and + * krb5_pkinit_get_kdc_cert_db(). + */ +extern void krb5_pkinit_release_cert_db( + krb5_pkinit_cert_db_t cert_db) +{ + if(cert_db == NULL) { + return; + } + CFRelease((CFTypeRef)cert_db); +} + + +/* + * Obtain a mallocd C-string representation of a certificate's SHA1 digest. + * Only error is a NULL return indicating memory failure. + * Caller must free the returned string. + */ +char *krb5_pkinit_cert_hash_str( + const krb5_data *cert) +{ + CC_SHA1_CTX ctx; + char *outstr; + char *cpOut; + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + unsigned dex; + + assert(cert != NULL); + CC_SHA1_Init(&ctx); + CC_SHA1_Update(&ctx, cert->data, cert->length); + CC_SHA1_Final(digest, &ctx); + + outstr = (char *)malloc((2 * CC_SHA1_DIGEST_LENGTH) + 1); + if(outstr == NULL) { + return NULL; + } + cpOut = outstr; + for(dex=0; dexdata = NULL; + kdc_cert->length = 0; + return 0; +} + +#endif /* APPLE_PKINIT */ diff --git a/krb5-1-7/src/lib/krb5/krb/pkinit_apple_client.c b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_client.c new file mode 100644 index 000000000..d98fc76c0 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_client.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_client.c - Client side routines for PKINIT, Mac OS X version + * + * Created 20 May 2004 by Doug Mitchell at Apple. + */ + +#if APPLE_PKINIT + +#include "pkinit_client.h" +#include "pkinit_asn1.h" +#include "pkinit_apple_utils.h" +#include "pkinit_cms.h" +#include +#include +#include +#include +#include + +/* + * Create a PA-PK-AS-REQ message. + */ +krb5_error_code krb5int_pkinit_as_req_create( + krb5_context context, + krb5_timestamp kctime, + krb5_int32 cusec, /* microseconds */ + krb5_ui_4 nonce, + const krb5_checksum *cksum, + krb5_pkinit_signing_cert_t client_cert, /* required */ + const krb5_data *trusted_CAs, /* optional list of CA certs */ + krb5_ui_4 num_trusted_CAs, + const krb5_data *kdc_cert, /* optional KDC cert */ + krb5_data *as_req) /* mallocd and RETURNED */ +{ + krb5_data auth_pack = {0}; + krb5_error_code krtn; + krb5_data content_info = {0}; + krb5int_algorithm_id *cms_types = NULL; + krb5_ui_4 num_cms_types = 0; + + /* issuer/serial numbers for trusted_CAs and kdc_cert, if we have them */ + krb5_data *ca_issuer_sn = NULL; /* issuer/serial_num for trusted_CAs */ + krb5_data kdc_issuer_sn = {0}; /* issuer/serial_num for kdc_cert */ + krb5_data *kdc_issuer_sn_p = NULL; + + /* optional platform-dependent CMS algorithm preference */ + krtn = krb5int_pkinit_get_cms_types(&cms_types, &num_cms_types); + if(krtn) { + return krtn; + } + + /* encode the core authPack */ + krtn = krb5int_pkinit_auth_pack_encode(kctime, cusec, nonce, cksum, + cms_types, num_cms_types, + &auth_pack); + if(krtn) { + goto errOut; + } + + /* package the AuthPack up in a SignedData inside a ContentInfo */ + krtn = krb5int_pkinit_create_cms_msg(&auth_pack, + client_cert, + NULL, /* recip_cert */ + ECT_PkAuthData, + 0, NULL, /* cms_types */ + &content_info); + if(krtn) { + goto errOut; + } + + /* if we have trusted_CAs, get issuer/serials */ + if(trusted_CAs) { + unsigned dex; + ca_issuer_sn = (krb5_data *)malloc(num_trusted_CAs * sizeof(krb5_data)); + if(ca_issuer_sn == NULL) { + krtn = ENOMEM; + goto errOut; + } + for(dex=0; dex +#include +#include +#include +#include +#include +#include + +/* + * Custom OIDS to specify as eContentType + */ +#define OID_PKINIT 0x2B, 6, 1, 5, 2, 3 +#define OID_PKINIT_LEN 6 + +static const uint8 OID_PKINIT_AUTH_DATA[] = {OID_PKINIT, 1}; +static const uint8 OID_PKINIT_RKEY_DATA[] = {OID_PKINIT, 3}; + +/* these may go public so keep these symbols private */ +static const CSSM_OID _CSSMOID_PKINIT_AUTH_DATA = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_AUTH_DATA}; +static const CSSM_OID _CSSMOID_PKINIT_RKEY_DATA = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_RKEY_DATA}; + + +#pragma mark ----- CMS utilities ---- + +#define CFRELEASE(cf) if(cf) { CFRelease(cf); } + +/* + * Convert platform-specific cert/signature status to krb5int_cert_sig_status. + */ +static krb5int_cert_sig_status pkiCertSigStatus( + OSStatus certStatus) +{ + switch(certStatus) { + case CSSM_OK: + return pki_cs_good; + case CSSMERR_CSP_VERIFY_FAILED: + return pki_cs_sig_verify_fail; + case CSSMERR_TP_NOT_TRUSTED: + return pki_cs_no_root; + case CSSMERR_TP_INVALID_ANCHOR_CERT: + return pki_cs_unknown_root; + case CSSMERR_TP_CERT_EXPIRED: + return pki_cs_expired; + case CSSMERR_TP_CERT_NOT_VALID_YET: + return pki_cs_not_valid_yet; + case CSSMERR_TP_CERT_REVOKED: + return pki_cs_revoked; + case KRB5_KDB_UNAUTH: + return pki_cs_untrusted; + case CSSMERR_TP_INVALID_CERTIFICATE: + return pki_cs_bad_leaf; + default: + return pki_cs_other_err; + } +} + +/* + * Infer krb5int_cert_sig_status from CMSSignerStatus and a CSSM TO + * cert veriofy result code (obtained via the certVerifyResultCode argument + * in CMSDecoderCopySignerStatus()). + */ +static krb5int_cert_sig_status pkiInferSigStatus( + CMSSignerStatus cms_status, + OSStatus tp_status) +{ + switch(cms_status) { + case kCMSSignerUnsigned: + return pki_not_signed; + case kCMSSignerValid: + return pki_cs_good; + case kCMSSignerNeedsDetachedContent: + return pki_bad_cms; + case kCMSSignerInvalidSignature: + return pki_cs_sig_verify_fail; + case kCMSSignerInvalidCert: + /* proceed with TP status */ + break; + default: + return pki_cs_other_err; + } + + /* signature good, infer end status from TP verify */ + return pkiCertSigStatus(tp_status); +} + +/* + * Cook up a SecCertificateRef from a krb5_data. + */ +static OSStatus pkiKrb5DataToSecCert( + const krb5_data *rawCert, + SecCertificateRef *secCert) /* RETURNED */ +{ + CSSM_DATA certData; + OSStatus ortn; + + assert((rawCert != NULL) && (secCert != NULL)); + + certData.Data = (uint8 *)rawCert->data; + certData.Length = rawCert->length; + ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, + CSSM_CERT_ENCODING_DER, secCert); + if(ortn) { + pkiCssmErr("SecCertificateCreateFromData", ortn); + } + return ortn; +} + +/* + * Convert CFArray of SecCertificateRefs to a mallocd array of krb5_datas. + */ +static krb5_error_code pkiCertArrayToKrb5Data( + CFArrayRef cf_certs, + unsigned *num_all_certs, + krb5_data **all_certs) +{ + CFIndex num_certs; + krb5_data *allCerts = NULL; + krb5_error_code krtn = 0; + CFIndex dex; + + if(cf_certs == NULL) { + *all_certs = NULL; + return 0; + } + num_certs = CFArrayGetCount(cf_certs); + *num_all_certs = (unsigned)num_certs; + if(num_certs == 0) { + *all_certs = NULL; + return 0; + } + allCerts = (krb5_data *)malloc(sizeof(krb5_data) * num_certs); + if(allCerts == NULL) { + return ENOMEM; + } + for(dex=0; dexdata, content->length, + &cf_content); + if(ortn) { + pkiCssmErr("CMSEncode", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + krtn = pkiCfDataToKrb5Data(cf_content, content_info); +errOut: + CFRELEASE(sec_recip); + CFRELEASE(cf_content); + return krtn; +} + +#pragma mark ----- Generalized parse ContentInfo ---- + +/* + * Parse a ContentInfo as best we can. All return fields are optional. + * If signer_cert_status is NULL on entry, NO signature or cert evaluation + * will be performed. + */ +krb5_error_code krb5int_pkinit_parse_cms_msg( + const krb5_data *content_info, + krb5_pkinit_cert_db_t cert_db, /* may be required for SignedData */ + krb5_boolean is_client_msg, /* TRUE : msg is from client */ + krb5_boolean *is_signed, /* RETURNED */ + krb5_boolean *is_encrypted, /* RETURNED */ + krb5_data *raw_data, /* RETURNED */ + krb5int_cms_content_type *inner_content_type,/* Returned, ContentType of */ + /* EncapsulatedData */ + krb5_data *signer_cert, /* RETURNED */ + krb5int_cert_sig_status *signer_cert_status,/* RETURNED */ + unsigned *num_all_certs, /* size of *all_certs RETURNED */ + krb5_data **all_certs) /* entire cert chain RETURNED */ +{ + SecPolicySearchRef policy_search = NULL; + SecPolicyRef policy = NULL; + OSStatus ortn; + krb5_error_code krtn = 0; + CMSDecoderRef decoder = NULL; + size_t num_signers; + CMSSignerStatus signer_status; + OSStatus cert_verify_status; + CFArrayRef cf_all_certs = NULL; + int msg_is_signed = 0; + + if(content_info == NULL) { + pkiDebug("krb5int_pkinit_parse_cms_msg: no ContentInfo\n"); + return KRB5_CRYPTO_INTERNAL; + } + + ortn = CMSDecoderCreate(&decoder); + if(ortn) { + return ENOMEM; + } + ortn = CMSDecoderUpdateMessage(decoder, content_info->data, content_info->length); + if(ortn) { + /* no verify yet, must be bad message */ + krtn = KRB5_PARSE_MALFORMED; + goto errOut; + } + ortn = CMSDecoderFinalizeMessage(decoder); + if(ortn) { + pkiCssmErr("CMSDecoderFinalizeMessage", ortn); + krtn = KRB5_PARSE_MALFORMED; + goto errOut; + } + + /* expect zero or one signers */ + ortn = CMSDecoderGetNumSigners(decoder, &num_signers); + switch(num_signers) { + case 0: + msg_is_signed = 0; + break; + case 1: + msg_is_signed = 1; + break; + default: + krtn = KRB5_PARSE_MALFORMED; + goto errOut; + } + + /* + * We need a cert verify policy even if we're not actually evaluating + * the cert due to requirements in libsecurity_smime. + */ + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + is_client_msg ? &CSSMOID_APPLE_TP_PKINIT_CLIENT : &CSSMOID_APPLE_TP_PKINIT_SERVER, + NULL, &policy_search); + if(ortn) { + pkiCssmErr("SecPolicySearchCreate", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + ortn = SecPolicySearchCopyNext(policy_search, &policy); + if(ortn) { + pkiCssmErr("SecPolicySearchCopyNext", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + + /* get some basic status that doesn't need heavyweight evaluation */ + if(msg_is_signed) { + if(is_signed) { + *is_signed = TRUE; + } + if(inner_content_type) { + CSSM_OID ec_oid = {0, NULL}; + CFDataRef ec_data = NULL; + + krb5int_cms_content_type ctype; + + ortn = CMSDecoderCopyEncapsulatedContentType(decoder, &ec_data); + if(ortn || (ec_data == NULL)) { + pkiCssmErr("CMSDecoderCopyEncapsulatedContentType", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + ec_oid.Data = (uint8 *)CFDataGetBytePtr(ec_data); + ec_oid.Length = CFDataGetLength(ec_data); + if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_Data)) { + ctype = ECT_Data; + } + else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_SignedData)) { + ctype = ECT_SignedData; + } + else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_EnvelopedData)) { + ctype = ECT_EnvelopedData; + } + else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_EncryptedData)) { + ctype = ECT_EncryptedData; + } + else if(pkiCompareCssmData(&ec_oid, &_CSSMOID_PKINIT_AUTH_DATA)) { + ctype = ECT_PkAuthData; + } + else if(pkiCompareCssmData(&ec_oid, &_CSSMOID_PKINIT_RKEY_DATA)) { + ctype = ECT_PkReplyKeyKata; + } + else { + ctype = ECT_Other; + } + *inner_content_type = ctype; + CFRelease(ec_data); + } + + /* + * Get SignedData's certs if the caller wants them + */ + if(all_certs) { + ortn = CMSDecoderCopyAllCerts(decoder, &cf_all_certs); + if(ortn) { + pkiCssmErr("CMSDecoderCopyAllCerts", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + krtn = pkiCertArrayToKrb5Data(cf_all_certs, num_all_certs, all_certs); + if(krtn) { + goto errOut; + } + } + + /* optional signer cert */ + if(signer_cert) { + SecCertificateRef sec_signer_cert = NULL; + CSSM_DATA cert_data; + + ortn = CMSDecoderCopySignerCert(decoder, 0, &sec_signer_cert); + if(ortn) { + /* should never happen if it's signed */ + pkiCssmErr("CMSDecoderCopySignerStatus", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + ortn = SecCertificateGetData(sec_signer_cert, &cert_data); + if(ortn) { + pkiCssmErr("SecCertificateGetData", ortn); + CFRelease(sec_signer_cert); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + krtn = pkiDataToKrb5Data(cert_data.Data, cert_data.Length, signer_cert); + CFRelease(sec_signer_cert); + if(krtn) { + goto errOut; + } + } + } + else { + /* not signed */ + if(is_signed) { + *is_signed = FALSE; + } + if(inner_content_type) { + *inner_content_type = ECT_Other; + } + if(signer_cert) { + signer_cert->data = NULL; + signer_cert->length = 0; + } + if(signer_cert_status) { + *signer_cert_status = pki_not_signed; + } + if(num_all_certs) { + *num_all_certs = 0; + } + if(all_certs) { + *all_certs = NULL; + } + } + if(is_encrypted) { + Boolean bencr; + ortn = CMSDecoderIsContentEncrypted(decoder, &bencr); + if(ortn) { + pkiCssmErr("CMSDecoderCopySignerStatus", ortn); + krtn = KRB5_CRYPTO_INTERNAL; + goto errOut; + } + *is_encrypted = bencr ? TRUE : FALSE; + } + + /* + * Verify signature and cert. The actual verify operation is optional, + * per our signer_cert_status argument, but we do this anyway if we need + * to get the signer cert. + */ + if((signer_cert_status != NULL) || (signer_cert != NULL)) { + + ortn = CMSDecoderCopySignerStatus(decoder, + 0, /* signerIndex */ + policy, + signer_cert_status ? TRUE : FALSE, /* evaluateSecTrust */ + &signer_status, + NULL, /* secTrust - not needed */ + &cert_verify_status); + if(ortn) { + /* gross error - subsequent processing impossible */ + pkiCssmErr("CMSDecoderCopySignerStatus", ortn); + krtn = KRB5_PARSE_MALFORMED; + goto errOut; + } + } + /* obtain & return status */ + if(signer_cert_status) { + *signer_cert_status = pkiInferSigStatus(signer_status, cert_verify_status); + } + + /* finally, the payload */ + if(raw_data) { + CFDataRef cf_content = NULL; + + ortn = CMSDecoderCopyContent(decoder, &cf_content); + if(ortn) { + pkiCssmErr("CMSDecoderCopyContent", ortn); + krtn = KRB5_PARSE_MALFORMED; + goto errOut; + } + krtn = pkiCfDataToKrb5Data(cf_content, raw_data); + CFRELEASE(cf_content); + } +errOut: + CFRELEASE(policy_search); + CFRELEASE(policy); + CFRELEASE(cf_all_certs); + CFRELEASE(decoder); + return krtn; +} + +krb5_error_code krb5int_pkinit_get_cms_types( + krb5int_algorithm_id **supported_cms_types, /* RETURNED */ + krb5_ui_4 *num_supported_cms_types) /* RETURNED */ +{ + /* no preference */ + *supported_cms_types = NULL; + *num_supported_cms_types = 0; + return 0; +} + +krb5_error_code krb5int_pkinit_free_cms_types( + krb5int_algorithm_id *supported_cms_types, + krb5_ui_4 num_supported_cms_types) +{ + /* + * We don't return anything from krb5int_pkinit_get_cms_types(), and + * if we did, it would be a pointer to a statically declared array, + * so this is a nop. + */ + return 0; +} + +#endif /* APPLE_PKINIT */ diff --git a/krb5-1-7/src/lib/krb5/krb/pkinit_apple_utils.c b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_utils.c new file mode 100644 index 000000000..f539693fd --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/pkinit_apple_utils.c @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Apple Inc. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Apple Inc. 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. + * + */ + +/* + * pkinit_apple_utils.c - PKINIT utilities, Mac OS X version + * + * Created 19 May 2004 by Doug Mitchell at Apple. + */ + +#if APPLE_PKINIT + +#include "pkinit_apple_utils.h" +#include "pkinit_asn1.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Cruft needed to attach to a module + */ +static CSSM_VERSION vers = {2, 0}; +static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; + +/* + * Standard app-level memory functions required by CDSA. + */ +static void * cuAppMalloc (CSSM_SIZE size, void *allocRef) { + return( malloc(size) ); +} + +static void cuAppFree (void *mem_ptr, void *allocRef) { + free(mem_ptr); + return; +} + +static void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + return( realloc( ptr, size ) ); +} + +static void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + return( calloc( num, size ) ); +} + +static CSSM_API_MEMORY_FUNCS memFuncs = { + cuAppMalloc, + cuAppFree, + cuAppRealloc, + cuAppCalloc, + NULL +}; + +/* + * Init CSSM; returns CSSM_FALSE on error. Reusable. + */ +static CSSM_BOOL cssmInitd = CSSM_FALSE; + +static CSSM_BOOL cuCssmStartup() +{ + CSSM_RETURN crtn; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + if(cssmInitd) { + return CSSM_TRUE; + } + crtn = CSSM_Init (&vers, + CSSM_PRIVILEGE_SCOPE_NONE, + &testGuid, + CSSM_KEY_HIERARCHY_NONE, + &pvcPolicy, + NULL /* reserved */); + if(crtn != CSSM_OK) + { + return CSSM_FALSE; + } + else { + cssmInitd = CSSM_TRUE; + return CSSM_TRUE; + } +} + +CSSM_CL_HANDLE pkiClStartup(void) +{ + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, + CSSM_KEY_HIERARCHY_NONE, + NULL, /* eventHandler */ + NULL); /* AppNotifyCallbackCtx */ + if(crtn) { + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, + &vers, + &memFuncs, /* memFuncs */ + 0, /* SubserviceID */ + CSSM_SERVICE_CL, /* SubserviceFlags - Where is this used? */ + 0, /* AttachFlags */ + CSSM_KEY_HIERARCHY_NONE, + NULL, /* FunctionTable */ + 0, /* NumFuncTable */ + NULL, /* reserved */ + &clHand); + if(crtn) { + return 0; + } + else { + return clHand; + } +} + +CSSM_RETURN pkiClDetachUnload( + CSSM_CL_HANDLE clHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(clHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); +} + +/* + * CSSM_DATA <--> krb5_ui_4 + */ +krb5_error_code pkiDataToInt( + const CSSM_DATA *cdata, + krb5_int32 *i) /* RETURNED */ +{ + krb5_ui_4 len; + krb5_int32 rtn = 0; + krb5_ui_4 dex; + uint8 *cp = NULL; + + if((cdata->Length == 0) || (cdata->Data == NULL)) { + *i = 0; + return 0; + } + len = cdata->Length; + if(len > sizeof(krb5_int32)) { + return ASN1_BAD_LENGTH; + } + + cp = cdata->Data; + for(dex=0; dexData[len - 1]; + for(i=0; i>= 8; + } + return 0; +} + +/* + * raw data --> krb5_data + */ +krb5_error_code pkiDataToKrb5Data( + const void *data, + unsigned dataLen, + krb5_data *kd) +{ + assert(data != NULL); + assert(kd != NULL); + kd->data = (char *)malloc(dataLen); + if(kd->data == NULL) { + return ENOMEM; + } + kd->length = dataLen; + memmove(kd->data, data, dataLen); + return 0; +} + +/* + * CSSM_DATA <--> krb5_data + * + * CSSM_DATA data is managed by a SecAsn1CoderRef; krb5_data data is mallocd. + * + * Both return nonzero on error. + */ +krb5_error_code pkiCssmDataToKrb5Data( + const CSSM_DATA *cd, + krb5_data *kd) +{ + assert(cd != NULL); + return pkiDataToKrb5Data(cd->Data, cd->Length, kd); +} + +krb5_error_code pkiKrb5DataToCssm( + const krb5_data *kd, + CSSM_DATA *cd, + SecAsn1CoderRef coder) +{ + assert((cd != NULL) && (kd != NULL)); + if(SecAsn1AllocCopy(coder, kd->data, kd->length, cd)) { + return ENOMEM; + } + return 0; +} + +/* + * CFDataRef --> krb5_data, mallocing the destination contents. + */ +krb5_error_code pkiCfDataToKrb5Data( + CFDataRef cfData, + krb5_data *kd) /* content mallocd and RETURNED */ +{ + return pkiDataToKrb5Data(CFDataGetBytePtr(cfData), + CFDataGetLength(cfData), kd); +} + +krb5_boolean pkiCompareCssmData( + const CSSM_DATA *d1, + const CSSM_DATA *d2) +{ + if((d1 == NULL) || (d2 == NULL)) { + return FALSE; + } + if(d1->Length != d2->Length) { + return FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return FALSE; + } + else { + return TRUE; + } +} + +/* + * krb5_timestamp --> a mallocd string in generalized format + */ +krb5_error_code pkiKrbTimestampToStr( + krb5_timestamp kts, + char **str) /* mallocd and RETURNED */ +{ + char *outStr = NULL; + time_t gmt_time = kts; + struct tm *utc = gmtime(&gmt_time); + if (utc == NULL || + utc->tm_year > 8099 || utc->tm_mon > 11 || + utc->tm_mday > 31 || utc->tm_hour > 23 || + utc->tm_min > 59 || utc->tm_sec > 59) { + return ASN1_BAD_GMTIME; + } + if (asprintf(&outStr, "%04d%02d%02d%02d%02d%02dZ", + utc->tm_year + 1900, utc->tm_mon + 1, + utc->tm_mday, utc->tm_hour, utc->tm_min, utc->tm_sec) < 0) { + return ENOMEM; + } + *str = outStr; + return 0; +} + +krb5_error_code pkiTimeStrToKrbTimestamp( + const char *str, + unsigned len, + krb5_timestamp *kts) /* RETURNED */ +{ + char szTemp[5]; + unsigned x; + unsigned i; + char *cp; + struct tm tmp; + time_t t; + + if(len != 15) { + return ASN1_BAD_LENGTH; + } + + if((str == NULL) || (kts == NULL)) { + return KRB5_CRYPTO_INTERNAL; + } + + cp = (char *)str; + memset(&tmp, 0, sizeof(tmp)); + + /* check that all characters except last are digits */ + for(i=0; i<(len - 1); i++) { + if ( !(isdigit(cp[i])) ) { + return ASN1_BAD_TIMEFORMAT; + } + } + + /* check last character is a 'Z' */ + if(cp[len - 1] != 'Z' ) { + return ASN1_BAD_TIMEFORMAT; + } + + /* YEAR */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = *cp++; + szTemp[3] = *cp++; + szTemp[4] = '\0'; + x = atoi( szTemp ); + /* by definition - tm_year is year - 1900 */ + tmp.tm_year = x - 1900; + + /* MONTH */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + /* in the string, months are from 1 to 12 */ + if((x > 12) || (x <= 0)) { + return ASN1_BAD_TIMEFORMAT; + } + /* in a tm, 0 to 11 */ + tmp.tm_mon = x - 1; + + /* DAY */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + /* 1..31 */ + if((x > 31) || (x <= 0)) { + return ASN1_BAD_TIMEFORMAT; + } + tmp.tm_mday = x; + + /* HOUR */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 23) || (x < 0)) { + return ASN1_BAD_TIMEFORMAT; + } + tmp.tm_hour = x; + + /* MINUTE */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return ASN1_BAD_TIMEFORMAT; + } + tmp.tm_min = x; + + /* SECOND */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return ASN1_BAD_TIMEFORMAT; + } + tmp.tm_sec = x; + t = timegm(&tmp); + if(t == -1) { + return ASN1_BAD_TIMEFORMAT; + } + *kts = t; + return 0; +} + +/* + * How many items in a NULL-terminated array of pointers? + */ +unsigned pkiNssArraySize( + const void **array) +{ + unsigned count = 0; + if (array) { + while (*array++) { + count++; + } + } + return count; +} + +#endif /* APPLE_PKINIT */ diff --git a/krb5-1-7/src/lib/krb5/krb/pr_to_salt.c b/krb5-1-7/src/lib/krb5/krb/pr_to_salt.c new file mode 100644 index 000000000..545d86fb1 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/preauth.c b/krb5-1-7/src/lib/krb5/krb/preauth.c new file mode 100644 index 000000000..2ef38c2c5 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/preauth.c @@ -0,0 +1,574 @@ +/* + * 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 +#include + +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) + free(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; + + free(scratch); + scratch = 0; + + retval = 0; + +cleanup: + if (scratch) + krb5_free_data(context, scratch); + if (enc_data.ciphertext.data) + free(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); + free(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; + struct k5buf buf; + + 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: + */ + krb5int_buf_init_dynamic(&buf); + if (challenge_len) { + krb5int_buf_add_len(&buf, label, label_len); + krb5int_buf_add(&buf, ": ["); + krb5int_buf_add_len(&buf, challenge, challenge_len); + krb5int_buf_add(&buf, "]\n"); + } + krb5int_buf_add_len(&buf, prompt, prompt_len); + krb5int_buf_add(&buf, ": "); + return krb5int_buf_data(&buf); +} + +/* + * 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) + free(sam_challenge); + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/preauth2.c b/krb5-1-7/src/lib/krb5/krb/preauth2.c new file mode 100644 index 000000000..ed05babe3 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/preauth2.c @@ -0,0 +1,2074 @@ +/* + * Copyright 1995, 2003, 2008 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" +#if APPLE_PKINIT +#include "pkinit_client.h" +#include "pkinit_cert_store.h" +#endif /* APPLE_PKINIT */ +#include "osconf.h" +#include +#include "int-proto.h" +#include "fast.h" + +#if !defined(_WIN32) +#include +#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 = calloc(n_modules, sizeof(context->modules[0])); + if (context->modules == NULL) { + krb5int_free_plugin_dir_data(tables); + free(context); + return; + } + 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 = 0; + 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 && 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; + krb5_error_code retval; + 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; + 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->etype; + *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; + case krb5plugin_preauth_client_fast_armor: { + krb5_keyblock *key = NULL; + ret = calloc(1, sizeof(krb5_data)); + if (ret == NULL) + return ENOMEM; + retval = 0; + if (rock->fast_state->armor_key) + retval = krb5_copy_keyblock(kcontext, rock->fast_state->armor_key, + &key); + if (retval == 0) { + ret->data = (char *) key; + ret->length = key?sizeof(krb5_keyblock):0; + key = NULL; + } + if (retval == 0) { + *retdata = ret; + ret = NULL; + } + if (ret) + free(ret); + return retval; + } + case krb5plugin_preauth_client_free_fast_armor: + ret = *retdata; + if (ret) { + if (ret->data) + krb5_free_keyblock(kcontext, (krb5_keyblock *) ret->data); + free(ret); + *retdata = NULL; + } + return 0; + 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 inline krb5_data +padata2data(krb5_pa_data p) +{ + krb5_data d; + d.magic = KV5M_DATA; + d.length = p.length; + d.data = (char *) p.contents; + return d; +} + +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 = padata2data(*in_padata); + 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_fx_cookie(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_pa_data *pa = calloc(1, sizeof(krb5_pa_data)); + krb5_octet *contents; + if (pa == NULL) + return ENOMEM; + contents = malloc(in_padata->length); + if (contents == NULL) { + free(pa); + return ENOMEM; + } + *pa = *in_padata; + pa->contents = contents; + memcpy(contents, in_padata->contents, pa->length); + *out_padata = pa; + 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) { + free(enc_data.ciphertext.data); + return(ret); + } + + ret = encode_krb5_enc_data(&enc_data, &tmp); + + free(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; + + free(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_free_sam_challenge(context, 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); + } + snprintf(name, sizeof(name), "%.*s", + SAMDATA(sam_challenge->sam_type_name, "SAM Authentication", + sizeof(name) - 1)); + + snprintf(banner, sizeof(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); */ + snprintf(prompt, sizeof(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_free_sam_challenge(context, 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_free_sam_challenge(context,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_free_sam_challenge(context, 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) + free(defsalt.data); + + if (ret) { + krb5_free_sam_challenge(context, 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_free_sam_challenge(context, 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) + free(defsalt.data); + + if (ret) { + krb5_free_sam_challenge(context, 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_free_sam_challenge(context, 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; + + free(scratch); + + return(0); +} + +#if APPLE_PKINIT +/* + * PKINIT. One function to generate AS-REQ, one to parse AS-REP + */ +#define PKINIT_DEBUG 0 +#if PKINIT_DEBUG +#define kdcPkinitDebug(args...) printf(args) +#else +#define kdcPkinitDebug(args...) +#endif + +static krb5_error_code pa_pkinit_gen_req( + 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 krtn; + krb5_data out_data = {0, 0, NULL}; + krb5_timestamp kctime = 0; + krb5_int32 cusec = 0; + krb5_ui_4 nonce = 0; + krb5_checksum cksum; + krb5_pkinit_signing_cert_t client_cert; + krb5_data *der_req = NULL; + char *client_principal = NULL; + char *server_principal = NULL; + unsigned char nonce_bytes[4]; + krb5_data nonce_data = {0, 4, (char *)nonce_bytes}; + int dex; + + /* + * Trusted CA list and specific KC cert optionally obtained via + * krb5_pkinit_get_server_certs(). All are DER-encoded certs. + */ + krb5_data *trusted_CAs = NULL; + krb5_ui_4 num_trusted_CAs; + krb5_data kdc_cert = {0}; + + kdcPkinitDebug("pa_pkinit_gen_req\n"); + + /* If we don't have a client cert, we're done */ + if(request->client == NULL) { + kdcPkinitDebug("No request->client; aborting PKINIT\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + krtn = krb5_unparse_name(context, request->client, &client_principal); + if(krtn) { + return krtn; + } + krtn = krb5_pkinit_get_client_cert(client_principal, &client_cert); + free(client_principal); + if(krtn) { + kdcPkinitDebug("No client cert; aborting PKINIT\n"); + return krtn; + } + + /* optional platform-dependent CA list and KDC cert */ + krtn = krb5_unparse_name(context, request->server, &server_principal); + if(krtn) { + goto cleanup; + } + krtn = krb5_pkinit_get_server_certs(client_principal, server_principal, + &trusted_CAs, &num_trusted_CAs, &kdc_cert); + if(krtn) { + goto cleanup; + } + + /* checksum of the encoded KDC-REQ-BODY */ + krtn = encode_krb5_kdc_req_body(request, &der_req); + if(krtn) { + kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); + goto cleanup; + } + krtn = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, der_req, &cksum); + if(krtn) { + goto cleanup; + } + + krtn = krb5_us_timeofday(context, &kctime, &cusec); + if(krtn) { + goto cleanup; + } + + /* cook up a random 4-byte nonce */ + krtn = krb5_c_random_make_octets(context, &nonce_data); + if(krtn) { + goto cleanup; + } + for(dex=0; dex<4; dex++) { + nonce <<= 8; + nonce |= nonce_bytes[dex]; + } + + krtn = krb5int_pkinit_as_req_create(context, + kctime, cusec, nonce, &cksum, + client_cert, + trusted_CAs, num_trusted_CAs, + (kdc_cert.data ? &kdc_cert : NULL), + &out_data); + if(krtn) { + kdcPkinitDebug("error %d on pkinit_as_req_create; aborting PKINIT\n", (int)krtn); + goto cleanup; + } + *out_padata = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); + if(*out_padata == NULL) { + krtn = ENOMEM; + free(out_data.data); + goto cleanup; + } + (*out_padata)->magic = KV5M_PA_DATA; + (*out_padata)->pa_type = KRB5_PADATA_PK_AS_REQ; + (*out_padata)->length = out_data.length; + (*out_padata)->contents = (krb5_octet *)out_data.data; + krtn = 0; +cleanup: + if(client_cert) { + krb5_pkinit_release_cert(client_cert); + } + if(cksum.contents) { + free(cksum.contents); + } + if (der_req) { + krb5_free_data(context, der_req); + } + if(server_principal) { + free(server_principal); + } + /* free data mallocd by krb5_pkinit_get_server_certs() */ + if(trusted_CAs) { + unsigned udex; + for(udex=0; udexrealm.length <= sizeof(lkdcprefix) || + 0 != memcmp(lkdcprefix, client->realm.data, sizeof(lkdcprefix)-1)) + return match; + realm_hash = &client->realm.data[sizeof(lkdcprefix)-1]; + realm_hash_len = client->realm.length - sizeof(lkdcprefix) + 1; + kdcPkinitDebug("checking realm versus certificate hash\n"); + if (NULL != (cert_hash = krb5_pkinit_cert_hash_str(signer_cert))) { + kdcPkinitDebug("hash = %s\n", cert_hash); + cert_hash_len = strlen(cert_hash); + if (cert_hash_len == realm_hash_len && + 0 == memcmp(cert_hash, realm_hash, cert_hash_len)) + match = TRUE; + free(cert_hash); + } + kdcPkinitDebug("result: %s\n", match ? "matches" : "does not match"); + return match; +} + +static krb5_error_code pa_pkinit_parse_rep( + 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) +{ + krb5int_cert_sig_status sig_status = (krb5int_cert_sig_status)-999; + krb5_error_code krtn; + krb5_data asRep; + krb5_keyblock local_key = {0}; + krb5_pkinit_signing_cert_t client_cert; + char *princ_name = NULL; + krb5_checksum as_req_checksum_rcd = {0}; /* received checksum */ + krb5_checksum as_req_checksum_gen = {0}; /* calculated checksum */ + krb5_data *encoded_as_req = NULL; + krb5_data signer_cert = {0}; + + *out_padata = NULL; + kdcPkinitDebug("pa_pkinit_parse_rep\n"); + if((in_padata == NULL) || (in_padata->length== 0)) { + kdcPkinitDebug("pa_pkinit_parse_rep: no in_padata\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + /* If we don't have a client cert, we're done */ + if(request->client == NULL) { + kdcPkinitDebug("No request->client; aborting PKINIT\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + krtn = krb5_unparse_name(context, request->client, &princ_name); + if(krtn) { + return krtn; + } + krtn = krb5_pkinit_get_client_cert(princ_name, &client_cert); + free(princ_name); + if(krtn) { + kdcPkinitDebug("No client cert; aborting PKINIT\n"); + return krtn; + } + + memset(&local_key, 0, sizeof(local_key)); + asRep.data = (char *)in_padata->contents; + asRep.length = in_padata->length; + krtn = krb5int_pkinit_as_rep_parse(context, &asRep, client_cert, + &local_key, &as_req_checksum_rcd, &sig_status, + &signer_cert, NULL, NULL); + if(krtn) { + kdcPkinitDebug("pkinit_as_rep_parse returned %d\n", (int)krtn); + return krtn; + } + switch(sig_status) { + case pki_cs_good: + break; + case pki_cs_unknown_root: + if (local_kdc_cert_match(context, &signer_cert, request->client)) + break; + /* FALLTHROUGH */ + default: + kdcPkinitDebug("pa_pkinit_parse_rep: bad cert/sig status %d\n", + (int)sig_status); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto error_out; + } + + /* calculate checksum of incoming AS-REQ using the decryption key + * we just got from the ReplyKeyPack */ + krtn = encode_krb5_as_req(request, &encoded_as_req); + if(krtn) { + goto error_out; + } + krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, + &local_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + encoded_as_req, &as_req_checksum_gen); + if(krtn) { + goto error_out; + } + if((as_req_checksum_gen.length != as_req_checksum_rcd.length) || + memcmp(as_req_checksum_gen.contents, + as_req_checksum_rcd.contents, + as_req_checksum_gen.length)) { + kdcPkinitDebug("pa_pkinit_parse_rep: checksum miscompare\n"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto error_out; + } + + /* We have the key; transfer to caller */ + if (as_key->length) { + krb5_free_keyblock_contents(context, as_key); + } + *as_key = local_key; + + #if PKINIT_DEBUG + fprintf(stderr, "pa_pkinit_parse_rep: SUCCESS\n"); + fprintf(stderr, "enctype %d keylen %d keydata %02x %02x %02x %02x...\n", + (int)as_key->enctype, (int)as_key->length, + as_key->contents[0], as_key->contents[1], + as_key->contents[2], as_key->contents[3]); + #endif + + krtn = 0; + +error_out: + if (signer_cert.data) { + free(signer_cert.data); + } + if(as_req_checksum_rcd.contents) { + free(as_req_checksum_rcd.contents); + } + if(as_req_checksum_gen.contents) { + free(as_req_checksum_gen.contents); + } + if(encoded_as_req) { + krb5_free_data(context, encoded_as_req); + } + if(krtn && (local_key.contents != NULL)) { + krb5_free_keyblock_contents(context, &local_key); + } + return krtn; +} +#endif /* APPLE_PKINIT */ + +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 (!krb5_c_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); + } + } + + snprintf(name, sizeof(name), "%.*s", + SAMDATA(sc2b->sam_type_name, "SAM Authentication", + sizeof(name) - 1)); + + snprintf(banner, sizeof(banner), "%.*s", + SAMDATA(sc2b->sam_challenge_label, + sam_challenge_banner(sc2b->sam_type), + sizeof(banner)-1)); + + snprintf(prompt, sizeof(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) free(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) free(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) free(defsalt.data); + return(retval); + } + krb5_free_keyblock_contents(context, &tmp_kb); + } + + if (defsalt.length) + free(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) + free(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); +} + +/* FIXME - order significant? */ +static const pa_types_t pa_types[] = { + { + KRB5_PADATA_PW_SALT, + pa_salt, + PA_INFO, + }, + { + KRB5_PADATA_AFS3_SALT, + pa_salt, + PA_INFO, + }, +#if APPLE_PKINIT + { + KRB5_PADATA_PK_AS_REQ, + pa_pkinit_gen_req, + PA_INFO, + }, + { + KRB5_PADATA_PK_AS_REP, + pa_pkinit_parse_rep, + PA_REAL, + }, +#endif /* APPLE_PKINIT */ + { + 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, + }, + { + KRB5_PADATA_FX_COOKIE, + pa_fx_cookie, + PA_INFO, + }, + { + -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) +{ + unsigned int h; + int 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 (krb5_c_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)))) { + if (paorder[h] == PA_INFO) { +#ifdef DEBUG + fprintf (stderr, + "internal function for type %d, flag %d " + "failed with err %d\n", + in_padata[i]->pa_type, paorder[h], ret); +#endif + ret = 0; + continue; /* PA_INFO type failed, ignore */ + } + + 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 = 0, 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-7/src/lib/krb5/krb/princ_comp.c b/krb5-1-7/src/lib/krb5/krb/princ_comp.c new file mode 100644 index 000000000..46e00e48d --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/princ_comp.c @@ -0,0 +1,179 @@ +/* + * lib/krb5/krb/princ_comp.c + * + * Copyright 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. + * + * + * compare two principals, returning a krb5_boolean true if equal, false if + * not. + */ + +#include "k5-int.h" +#include "k5-unicode.h" + +static krb5_boolean +realm_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + const krb5_data *realm1 = krb5_princ_realm(context, princ1); + const krb5_data *realm2 = krb5_princ_realm(context, princ2); + + if (realm1->length != realm2->length) + return FALSE; + + return (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) ? + (strncasecmp(realm1->data, realm2->data, realm2->length) == 0) : + (memcmp(realm1->data, realm2->data, realm2->length) == 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) +{ + return realm_compare_flags(context, princ1, princ2, 0); +} + +static krb5_error_code +upn_to_principal(krb5_context context, + krb5_const_principal princ, + krb5_principal *upn) +{ + char *unparsed_name; + krb5_error_code code; + + code = krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &unparsed_name); + if (code) { + *upn = NULL; + return code; + } + + code = krb5_parse_name(context, unparsed_name, upn); + + free(unparsed_name); + + return code; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + register int i; + krb5_int32 nelem; + unsigned int utf8 = (flags & KRB5_PRINCIPAL_COMPARE_UTF8) != 0; + unsigned int casefold = (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) != 0; + krb5_principal upn1 = NULL; + krb5_principal upn2 = NULL; + krb5_boolean ret = FALSE; + + if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) { + /* Treat UPNs as if they were real principals */ + if (krb5_princ_type(context, princ1) == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ1, &upn1) == 0) + princ1 = upn1; + } + if (krb5_princ_type(context, princ2) == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ2, &upn2) == 0) + princ2 = upn2; + } + } + + nelem = krb5_princ_size(context, princ1); + if (nelem != krb5_princ_size(context, princ2)) + goto out; + + if ((flags & KRB5_PRINCIPAL_COMPARE_IGNORE_REALM) == 0 && + !realm_compare_flags(context, princ1, princ2, flags)) + goto out; + + 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); + int cmp; + + if (casefold) { + if (utf8) + cmp = krb5int_utf8_normcmp(p1, p2, KRB5_UTF8_CASEFOLD); + else + cmp = p1->length == p2->length ? + strncasecmp(p1->data, p2->data, p2->length) : + p1->length - p2->length; + } else + cmp = !data_eq(*p1, *p2); + + if (cmp != 0) + goto out; + } + + ret = TRUE; + +out: + if (upn1 != NULL) + krb5_free_principal(context, upn1); + if (upn2 != NULL) + krb5_free_principal(context, upn2); + + return ret; +} + +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; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, KRB5_PRINCIPAL_COMPARE_IGNORE_REALM); +} + diff --git a/krb5-1-7/src/lib/krb5/krb/rd_cred.c b/krb5-1-7/src/lib/krb5/krb/rd_cred.c new file mode 100644 index 000000000..48637450d --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_cred.c @@ -0,0 +1,245 @@ +#include "k5-int.h" +#include "cleanup.h" +#include "auth_con.h" + +#include /* NULL */ +#include /* malloc */ +#include /* 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)); + free(ppart); + } + memset(scratch.data, 0, scratch.length); + free(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 *)calloc(1, sizeof(krb5_creds))) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + (*pppcreds)[i] = pcur; + (*pppcreds)[i+1] = 0; + pinfo = encpart.ticket_info[i++]; + + 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; + free(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 -----------------------*/ + +/* + * 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; + + if ((retval = krb5int_check_clockskew(context, replaydata.timestamp))) + goto error; + + if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, + "_forw", &replay.client))) + goto error; + + replay.server = ""; /* XXX */ + replay.msghash = NULL; + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { + free(replay.client); + goto error; + } + free(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-7/src/lib/krb5/krb/rd_error.c b/krb5-1-7/src/lib/krb5/krb/rd_error.c new file mode 100644 index 000000000..2c617154b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_error.c @@ -0,0 +1,50 @@ +/* + * 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-7/src/lib/krb5/krb/rd_priv.c b/krb5-1-7/src/lib/krb5/krb/rd_priv.c new file mode 100644 index 000000000..eaeaed894 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_priv.c @@ -0,0 +1,275 @@ +/* + * lib/krb5/krb/rd_priv.c + * + * Copyright 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. + * + * + * krb5_rd_priv() + */ + +#include "k5-int.h" +#include "cleanup.h" +#include "auth_con.h" + +/* + +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); + free(scratch.data); + +cleanup_privmsg:; + free(privmsg->enc_part.ciphertext.data); + free(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->remote_addr) + return KRB5_REMOTE_ADDR_REQUIRED; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && + (auth_context->rcache == NULL)) + return KRB5_RC_REQUIRED; + +{ + krb5_address * premote_fulladdr; + 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_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; + } + + memset(&replaydata, 0, sizeof(replaydata)); + 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; + + if ((retval = krb5int_check_clockskew(context, replaydata.timestamp))) + goto error; + + if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, + "_priv", &replay.client))) + goto error; + + replay.server = ""; /* XXX */ + replay.msghash = NULL; + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { + free(replay.client); + goto error; + } + free(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:; + free(outbuf->data); + outbuf->length = 0; + outbuf->data = NULL; + + return retval; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/rd_rep.c b/krb5-1-7/src/lib/krb5/krb/rd_rep.c new file mode 100644 index 000000000..2d495ae8f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_rep.c @@ -0,0 +1,202 @@ +/* + * 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() + */ +/* + * Copyright (c) 2006-2008, 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" +#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; + } + /* not used for anything yet */ + auth_context->negotiated_etype = (*repl)->subkey->enctype; + } + + /* 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; +} + +krb5_error_code KRB5_CALLCONV +krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_ui_4 *nonce) +{ + krb5_error_code retval; + krb5_ap_rep * reply; + krb5_data scratch; + krb5_ap_rep_enc_part *repl = NULL; + + 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; + + *nonce = repl->seq_number; + if (*nonce != auth_context->local_seq_number) { + retval = KRB5_MUTUAL_FAILED; + goto clean_scratch; + } + + /* Must be NULL to prevent echoing for client AP-REP */ + if (repl->subkey != NULL) { + retval = KRB5_MUTUAL_FAILED; + goto clean_scratch; + } + +clean_scratch: + memset(scratch.data, 0, scratch.length); + + if (repl != NULL) + krb5_free_ap_rep_enc_part(context, repl); + krb5_free_ap_rep(context, reply); + free(scratch.data); + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/rd_req.c b/krb5-1-7/src/lib/krb5/krb/rd_req.c new file mode 100644 index 000000000..5848aa776 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_req.c @@ -0,0 +1,108 @@ +/* + * lib/krb5/krb/rd_req.c + * + * Copyright 1990,1991, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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) +{ + 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; +#ifndef LEAN_CLIENT + if ((retval = decode_krb5_ap_req(inbuf, &request))) { + switch (retval) { + case KRB5_BADMSGTYPE: + return KRB5KRB_AP_ERR_BADVERSION; + default: + return(retval); + } + } +#endif /* LEAN_CLIENT */ + + /* 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; + } + + +#ifndef LEAN_CLIENT + /* Get a keytab if necessary. */ + if (keytab == NULL) { + if ((retval = krb5_kt_default(context, &new_keytab))) + goto cleanup_auth_context; + keytab = new_keytab; + } +#endif /* LEAN_CLIENT */ + + retval = krb5_rd_req_decoded(context, auth_context, request, server, + keytab, ap_req_options, ticket); + +#ifndef LEAN_CLIENT + if (new_keytab != NULL) + (void) krb5_kt_close(context, new_keytab); +#endif /* LEAN_CLIENT */ + +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-7/src/lib/krb5/krb/rd_req_dec.c b/krb5-1-7/src/lib/krb5/krb/rd_req_dec.c new file mode 100644 index 000000000..c618be1ee --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_req_dec.c @@ -0,0 +1,717 @@ +/* + * lib/krb5/krb/rd_req_dec.c + * + * Copyright (c) 1994 CyberSAFE Corporation. + * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your 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); +static krb5_error_code +decode_etype_list(krb5_context context, + const krb5_authenticator *authp, + krb5_enctype **desired_etypes, + int *desired_etypes_len); +static krb5_error_code +negotiate_etype(krb5_context context, + const krb5_enctype *desired_etypes, + int desired_etypes_len, + int mandatory_etypes_index, + const krb5_enctype *permitted_etypes, + int permitted_etypes_len, + krb5_enctype *negotiated_etype); + +krb5_error_code +krb5int_check_clockskew(krb5_context context, krb5_timestamp date) +{ + krb5_timestamp currenttime; + krb5_error_code retval; + + retval = krb5_timeofday(context, ¤ttime); + if (retval) + return retval; + if (!(labs((date)-currenttime) < context->clockskew)) + return KRB5KRB_AP_ERR_SKEW; + return 0; +} + +static krb5_error_code +krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req, + krb5_const_principal server, krb5_keytab keytab) +{ + krb5_error_code retval; + krb5_keytab_entry ktent; + + retval = KRB5_KT_NOTFOUND; + +#ifndef LEAN_CLIENT + if (server != NULL || keytab->ops->start_seq_get == NULL) { + retval = krb5_kt_get_entry(context, keytab, + server != NULL ? server : req->ticket->server, + req->ticket->enc_part.kvno, + req->ticket->enc_part.enctype, &ktent); + if (retval == 0) { + retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket); + + (void) krb5_free_keytab_entry_contents(context, &ktent); + } + } else { + krb5_error_code code; + krb5_kt_cursor cursor; + + retval = krb5_kt_start_seq_get(context, keytab, &cursor); + if (retval != 0) + goto map_error; + + while ((code = krb5_kt_next_entry(context, keytab, + &ktent, &cursor)) == 0) { + if (ktent.key.enctype != req->ticket->enc_part.enctype) + continue; + + retval = krb5_decrypt_tkt_part(context, &ktent.key, + req->ticket); + + if (retval == 0) { + krb5_principal tmp; + + /* + * We overwrite ticket->server to be the principal + * that we match in the keytab. The reason for doing + * this is that GSS-API and other consumers look at + * that principal to make authorization decisions + * about whether the appropriate server is contacted. + * It might be cleaner to create a new API and store + * the server in the auth_context, but doing so would + * probably miss existing uses of the server. Instead, + * perhaps an API should be created to retrieve the + * server as it appeared in the ticket. + */ + retval = krb5_copy_principal(context, ktent.principal, &tmp); + if (retval == 0) { + krb5_free_principal(context, req->ticket->server); + req->ticket->server = tmp; + } + (void) krb5_free_keytab_entry_contents(context, &ktent); + break; + } + (void) krb5_free_keytab_entry_contents(context, &ktent); + } + + code = krb5_kt_end_seq_get(context, keytab, &cursor); + if (code != 0) + retval = code; + } +#endif /* LEAN_CLIENT */ + +map_error: + switch (retval) { + case KRB5_KT_KVNONOTFOUND: + case KRB5_KT_NOTFOUND: + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + retval = KRB5KRB_AP_WRONG_PRINC; + break; + default: + break; + } + + return retval; +} + +#if 0 +#include +static void +debug_log_authz_data(const char *which, krb5_authdata **a) +{ + if (a) { + syslog(LOG_ERR|LOG_DAEMON, "%s authz data:", which); + while (*a) { + syslog(LOG_ERR|LOG_DAEMON, " ad_type:%d length:%d '%.*s'", + (*a)->ad_type, (*a)->length, (*a)->length, + (char *) (*a)->contents); + a++; + } + syslog(LOG_ERR|LOG_DAEMON, " [end]"); + } else + syslog(LOG_ERR|LOG_DAEMON, "no %s authz data", which); +} +#else +static void +debug_log_authz_data(const char *which, krb5_authdata **a) +{ +} +#endif + +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_principal_data princ_data; + krb5_enctype *desired_etypes = NULL; + int desired_etypes_len = 0; + int rfc4537_etypes_len = 0; + krb5_enctype *permitted_etypes = NULL; + int permitted_etypes_len = 0; + + 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 (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, server, 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 */ +#ifndef LEAN_CLIENT + if ((retval = decrypt_authenticator(context, req, + &((*auth_context)->authentp), + check_valid_flag))) + goto cleanup; +#endif + 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; + } + + if (!server) { + server = req->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; + } + /* 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]) || + !data_eq_string(*realm, 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_hash_message(context, + &req->authenticator.ciphertext, + &rep.msghash); + if (!retval) { + retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); + free(rep.msghash); + } + free(rep.server); + free(rep.client); + } + + if (retval) + goto cleanup; + } + + retval = krb5_validate_times(context, &req->ticket->enc_part2->times); + if (retval != 0) + goto cleanup; + + if ((retval = krb5int_check_clockskew(context, (*auth_context)->authentp->ctime))) + goto cleanup; + + if (check_valid_flag) { + if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { + retval = KRB5KRB_AP_ERR_TKT_INVALID; + goto cleanup; + } + } + + /* read RFC 4537 etype list from sender */ + retval = decode_etype_list(context, + (*auth_context)->authentp, + &desired_etypes, + &rfc4537_etypes_len); + if (retval != 0) + goto cleanup; + + if (desired_etypes == NULL) + desired_etypes = (krb5_enctype *)calloc(4, sizeof(krb5_enctype)); + else + desired_etypes = (krb5_enctype *)realloc(desired_etypes, + (rfc4537_etypes_len + 4) * + sizeof(krb5_enctype)); + if (desired_etypes == NULL) { + retval = ENOMEM; + goto cleanup; + } + + desired_etypes_len = rfc4537_etypes_len; + + /* + * RFC 4537: + * + * If the EtypeList is present and the server prefers an enctype from + * the client's enctype list over that of the AP-REQ authenticator + * subkey (if that is present) or the service ticket session key, the + * server MUST create a subkey using that enctype. This negotiated + * subkey is sent in the subkey field of AP-REP message, and it is then + * used as the protocol key or base key [RFC3961] for subsequent + * communication. + * + * If the enctype of the ticket session key is included in the enctype + * list sent by the client, it SHOULD be the last on the list; + * otherwise, this enctype MUST NOT be negotiated if it was not included + * in the list. + * + * The second paragraph does appear to contradict the first with respect + * to whether it is legal to negotiate the ticket session key type if it + * is absent in the EtypeList. A literal reading suggests that we can use + * the AP-REQ subkey enctype. Also a client has no way of distinguishing + * a server that does not RFC 4537 from one that has chosen the same + * enctype as the ticket session key for the acceptor subkey, surely. + */ + + if ((*auth_context)->authentp->subkey != NULL) { + desired_etypes[desired_etypes_len++] = (*auth_context)->authentp->subkey->enctype; + } + desired_etypes[desired_etypes_len++] = req->ticket->enc_part2->session->enctype; + desired_etypes[desired_etypes_len] = ENCTYPE_NULL; + + if (((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) == 0) { + if ((*auth_context)->permitted_etypes != NULL) { + permitted_etypes = (*auth_context)->permitted_etypes; + } else { + retval = krb5_get_permitted_enctypes(context, &permitted_etypes); + if (retval != 0) + goto cleanup; + } + for (permitted_etypes_len = 0; + permitted_etypes[permitted_etypes_len] != ENCTYPE_NULL; + permitted_etypes_len++) + ; + } else { + permitted_etypes = NULL; + permitted_etypes_len = 0; + } + + /* check if the various etypes are permitted */ + retval = negotiate_etype(context, + desired_etypes, desired_etypes_len, + rfc4537_etypes_len, + permitted_etypes, permitted_etypes_len, + &(*auth_context)->negotiated_etype); + if (retval != 0) + goto cleanup; + + assert((*auth_context)->negotiated_etype != ENCTYPE_NULL); + + (*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; + + debug_log_authz_data("ticket", req->ticket->enc_part2->authorization_data); + + /* + * 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 & AP_OPTS_WIRE_MASK; + if (rfc4537_etypes_len != 0) + *ap_req_options |= AP_OPTS_ETYPE_NEGOTIATION; + if ((*auth_context)->negotiated_etype != (*auth_context)->keyblock->enctype) + *ap_req_options |= AP_OPTS_USE_SUBKEY; + } + + retval = 0; + +cleanup: + if (desired_etypes != NULL) + free(desired_etypes); + if (permitted_etypes != NULL && + permitted_etypes != (*auth_context)->permitted_etypes) + free(permitted_etypes); + 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; +} + +#ifndef LEAN_CLIENT +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; + debug_log_authz_data("authenticator", local_auth->authorization_data); + } + clean_scratch(); + return retval; +} +#endif + +static krb5_error_code +negotiate_etype(krb5_context context, + const krb5_enctype *desired_etypes, + int desired_etypes_len, + int mandatory_etypes_index, + const krb5_enctype *permitted_etypes, + int permitted_etypes_len, + krb5_enctype *negotiated_etype) +{ + int i, j; + + *negotiated_etype = ENCTYPE_NULL; + + /* mandatory segment of desired_etypes must be permitted */ + for (i = mandatory_etypes_index; i < desired_etypes_len; i++) { + krb5_boolean permitted = FALSE; + + for (j = 0; j < permitted_etypes_len; j++) { + if (desired_etypes[i] == permitted_etypes[j]) { + permitted = TRUE; + break; + } + } + + if (permitted == FALSE) { + char enctype_name[30]; + + if (krb5_enctype_to_string(desired_etypes[i], + enctype_name, + sizeof(enctype_name)) == 0) + krb5_set_error_message(context, KRB5_NOPERM_ETYPE, + "Encryption type %s not permitted", + enctype_name); + return KRB5_NOPERM_ETYPE; + } + } + + /* + * permitted_etypes is ordered from most to least preferred; + * find first desired_etype that matches. + */ + for (j = 0; j < permitted_etypes_len; j++) { + for (i = 0; i < desired_etypes_len; i++) { + if (desired_etypes[i] == permitted_etypes[j]) { + *negotiated_etype = permitted_etypes[j]; + return 0; + } + } + } + + /*NOTREACHED*/ + return KRB5_NOPERM_ETYPE; +} + +static krb5_error_code +decode_etype_list(krb5_context context, + const krb5_authenticator *authp, + krb5_enctype **desired_etypes, + int *desired_etypes_len) +{ + krb5_error_code code; + krb5_authdata **ad_if_relevant = NULL; + krb5_authdata *etype_adata = NULL; + krb5_etype_list *etype_list = NULL; + int i, j; + krb5_data data; + + *desired_etypes = NULL; + + if (authp->authorization_data == NULL) + return 0; + + /* + * RFC 4537 says that ETYPE_NEGOTIATION auth data should be wrapped + * in AD_IF_RELEVANT, but we handle the case where it is mandatory. + */ + for (i = 0; authp->authorization_data[i] != NULL; i++) { + switch (authp->authorization_data[i]->ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: + code = krb5_decode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + authp->authorization_data[i], + &ad_if_relevant); + if (code != 0) + continue; + + for (j = 0; ad_if_relevant[j] != NULL; j++) { + if (ad_if_relevant[j]->ad_type == KRB5_AUTHDATA_ETYPE_NEGOTIATION) { + etype_adata = ad_if_relevant[j]; + break; + } + } + if (etype_adata == NULL) { + krb5_free_authdata(context, ad_if_relevant); + ad_if_relevant = NULL; + } + break; + case KRB5_AUTHDATA_ETYPE_NEGOTIATION: + etype_adata = authp->authorization_data[i]; + break; + default: + break; + } + if (etype_adata != NULL) + break; + } + + if (etype_adata == NULL) + return 0; + + data.data = (char *)etype_adata->contents; + data.length = etype_adata->length; + + code = decode_krb5_etype_list(&data, &etype_list); + if (code == 0) { + *desired_etypes = etype_list->etypes; + *desired_etypes_len = etype_list->length; + free(etype_list); + } + + if (ad_if_relevant != NULL) + krb5_free_authdata(context, ad_if_relevant); + + return code; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/rd_safe.c b/krb5-1-7/src/lib/krb5/krb/rd_safe.c new file mode 100644 index 000000000..9d5db1f87 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/rd_safe.c @@ -0,0 +1,279 @@ +/* + * lib/krb5/krb/rd_safe.c + * + * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" + +/* + 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; + struct krb5_safe_with_body swb; + + 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; + + swb.body = &safe_body; + swb.safe = message; + retval = encode_krb5_safe_with_body(&swb, &scratch); + message->checksum = his_cksum; + if (retval) + goto cleanup; + + 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; + + if (!auth_context->remote_addr) + return KRB5_REMOTE_ADDR_REQUIRED; + + /* Get keyblock */ + if ((keyblock = auth_context->recv_subkey) == NULL) + keyblock = auth_context->keyblock; + +{ + krb5_address * premote_fulladdr; + 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_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; + } + + memset(&replaydata, 0, sizeof(replaydata)); + 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; + + if ((retval = krb5int_check_clockskew(context, replaydata.timestamp))) + goto error; + + if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, + "_safe", &replay.client))) + goto error; + + replay.server = ""; /* XXX */ + replay.msghash = NULL; + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { + free(replay.client); + goto error; + } + free(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: + free(outbuf->data); + return retval; + +} + diff --git a/krb5-1-7/src/lib/krb5/krb/recvauth.c b/krb5-1-7/src/lib/krb5/krb/recvauth.c new file mode 100644 index 000000000..ab3e1e48a --- /dev/null +++ b/krb5-1-7/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 +#include +#include + +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; + } + free(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 + free(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); + free(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) { + free(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); + free(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-7/src/lib/krb5/krb/send_tgs.c b/krb5-1-7/src/lib/krb5/krb/send_tgs.c new file mode 100644 index 000000000..c23a5a371 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/send_tgs.c @@ -0,0 +1,345 @@ +/* + * lib/krb5/krb/send_tgs.c + * + * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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" + +/* +Constructs a TGS request + 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 +tgs_construct_tgsreq(krb5_context context, krb5_data *in_data, + krb5_creds *in_cred, krb5_data *outbuf, krb5_keyblock *subkey) +{ + krb5_cksumtype cksumtype; + krb5_error_code retval; + krb5_checksum checksum; + krb5_authenticator authent; + krb5_ap_req request; + krb5_data * scratch = NULL; + krb5_data * toutbuf = NULL; + + checksum.contents = NULL; + request.authenticator.ciphertext.data = NULL; + request.authenticator.kvno = 0; + request.ap_options = 0; + request.ticket = 0; + switch (in_cred->keyblock.enctype) { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + cksumtype = context->kdc_req_sumtype; + break; + default: + retval = krb5int_c_mandatory_cksumtype(context, in_cred->keyblock.enctype, &cksumtype); + if (retval) + goto cleanup; + } + + /* Generate checksum */ + if ((retval = krb5_c_make_checksum(context, cksumtype, + &in_cred->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + in_data, &checksum))) { + free(checksum.contents); + goto cleanup; + } + + /* gen authenticator */ + authent.subkey = subkey; /*owned by caller*/ + 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))) + goto cleanup; + + + /* encode the authenticator */ + if ((retval = encode_krb5_authenticator(&authent, &scratch))) + goto cleanup; + + free(checksum.contents); + checksum.contents = NULL; + + + if ((retval = decode_krb5_ticket(&(in_cred)->ticket, &request.ticket))) + /* Cleanup scratch and scratch data */ + goto cleanup; + + /* call the encryption routine */ + if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH, + scratch, &request.authenticator))) + goto cleanup; + + if (!(retval = encode_krb5_ap_req(&request, &toutbuf))) { + *outbuf = *toutbuf; + free(toutbuf); + } + + memset(request.authenticator.ciphertext.data, 0, + request.authenticator.ciphertext.length); + free(request.authenticator.ciphertext.data); + request.authenticator.ciphertext.length = 0; + request.authenticator.ciphertext.data = 0; + + +cleanup: + if (request.ticket) + krb5_free_ticket(context, request.ticket); + + if (scratch != NULL && scratch->data != NULL) { + zap(scratch->data, scratch->length); + free(scratch->data); + } + free(scratch); + + return retval; +} +/* + * Note that this function fills in part of rep even on failure. + */ +krb5_error_code +krb5int_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_keyblock **subkey) +{ + 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; + krb5_keyblock *local_subkey = NULL; + + assert (subkey != NULL); + *subkey = NULL; + /* + * 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.authorization_data.ciphertext.data = NULL; + 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; + rep->message_type = KRB5_ERROR; /*caller only uses the response + * element on successful return*/ + + tgsreq.addresses = (krb5_address **) addrs; + + /* Generate subkey*/ + if ((retval = krb5_generate_subkey( context, &in_cred->keyblock, + &local_subkey)) != 0) + return retval; + + if (authorization_data) { + /* need to encrypt it in the request */ + + if ((retval = encode_krb5_authdata(authorization_data, &scratch))) + goto send_tgs_error_1; + + if ((retval = krb5_encrypt_helper(context, local_subkey, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, + scratch, + &tgsreq.authorization_data))) { + free(tgsreq.authorization_data.ciphertext.data); + krb5_free_data(context, scratch); + goto send_tgs_error_1; + } + + 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 = tgs_construct_tgsreq(context, scratch, in_cred, + &scratch2, local_subkey))) { + 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) { + free(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) { + free(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))) { + free(ap_req_padata.contents); + free(combined_padata); + goto send_tgs_error_2; + } + free(ap_req_padata.contents); + free(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 = NULL; + 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; + *subkey = local_subkey; + } 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) + free(tgsreq.ktype); + if (tgsreq.authorization_data.ciphertext.data) { + memset(tgsreq.authorization_data.ciphertext.data, 0, + tgsreq.authorization_data.ciphertext.length); + free(tgsreq.authorization_data.ciphertext.data); + } + if (rep->message_type != KRB5_TGS_REP && local_subkey){ + krb5_free_keyblock(context, *subkey); + } + + return retval; +} + diff --git a/krb5-1-7/src/lib/krb5/krb/sendauth.c b/krb5-1-7/src/lib/krb5/krb/sendauth.c new file mode 100644 index 000000000..a082b8258 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/sendauth.c @@ -0,0 +1,236 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/krb5/krb/sendauth.c + * + * Copyright 1991, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 +#include +#include + +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[2]; + 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[0].length = strlen(sendauth_version) + 1; + outbuf[0].data = (char *) sendauth_version; + outbuf[1].length = strlen(appl_version) + 1; + outbuf[1].data = appl_version; + if ((retval = krb5int_write_messages(context, fd, outbuf, 2))) + 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); + } + } + + outbuf[0].data = NULL; /* Coverity is confused otherwise */ + if ((retval = krb5_mk_req_extended(context, auth_context, + ap_req_options, in_data, credsp, + &outbuf[0]))) + goto error_return; + + /* + * First write the length of the AP_REQ message, then write + * the message itself. + */ + retval = krb5_write_message(context, fd, &outbuf[0]); + free(outbuf[0].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))) { + free(inbuf.data); + goto error_return; + } + } + retval = KRB5_SENDAUTH_REJECTED; + free(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); + free(inbuf.data); + goto error_return; + } + + free(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-7/src/lib/krb5/krb/ser_actx.c b/krb5-1-7/src/lib/krb5/krb/ser_actx.c new file mode 100644 index 000000000..347b300f5 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_actx.c @@ -0,0 +1,564 @@ +/* + * lib/krb5/krb/ser_actx.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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) + calloc(1, 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); +#ifndef LEAN_CLIENT + if (!kret) + kret = krb5_ser_authenticator_init(kcontext); +#endif + 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-7/src/lib/krb5/krb/ser_adata.c b/krb5-1-7/src/lib/krb5/krb/ser_adata.c new file mode 100644 index 000000000..82d04dce1 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_adata.c @@ -0,0 +1,198 @@ +/* + * lib/krb5/krb/ser_adata.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *) calloc(1, 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-7/src/lib/krb5/krb/ser_addr.c b/krb5-1-7/src/lib/krb5/krb/ser_addr.c new file mode 100644 index 000000000..11b7f6abf --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_addr.c @@ -0,0 +1,202 @@ +/* + * lib/krb5/krb/ser_addr.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *) calloc(1, 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-7/src/lib/krb5/krb/ser_auth.c b/krb5-1-7/src/lib/krb5/krb/ser_auth.c new file mode 100644 index 000000000..6951f92fa --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_auth.c @@ -0,0 +1,349 @@ +/* + * lib/krb5/krb/ser_auth.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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. + */ + +#ifndef LEAN_CLIENT + +#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 *) + calloc(1, 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 **) + calloc(len, sizeof(krb5_authdata *)))) { + for (i=0; !kret && (i + 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)); +} +#endif diff --git a/krb5-1-7/src/lib/krb5/krb/ser_cksum.c b/krb5-1-7/src/lib/krb5/krb/ser_cksum.c new file mode 100644 index 000000000..8d2870249 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_cksum.c @@ -0,0 +1,200 @@ +/* + * lib/krb5/krb/ser_cksum.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *) calloc(1, 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-7/src/lib/krb5/krb/ser_ctx.c b/krb5-1-7/src/lib/krb5/krb/ser_ctx.c new file mode 100644 index 000000000..12051d7c4 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_ctx.c @@ -0,0 +1,621 @@ +/* + * lib/krb5/krb/ser_ctx.c + * + * Copyright 1995, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *); +#ifndef LEAN_CLIENT +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 *); +#endif /* LEAN_CLIENT */ + +/* 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 */ +}; +#ifndef LEAN_CLIENT +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 */ +}; +#endif /* LEAN_CLIENT */ +/* + * 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 + * <> 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 */ + 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->dal_handle) + kret = krb5_size_opaque(kcontext, + KV5M_DB_CONTEXT, + (krb5_pointer) context->dal_handle, + &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; + unsigned 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; iin_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; itgs_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 handle os_context, if appropriate */ + 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->dal_handle) { + kret = krb5_externalize_opaque(kcontext, KV5M_DB_CONTEXT, + (krb5_pointer) context->dal_handle, + &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; + unsigned 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) calloc(1, sizeof(struct _krb5_context)); + if (!context) + return (ENOMEM); + + /* 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 *) calloc(context->in_tkt_ktype_count+1, + sizeof(krb5_enctype)); + if (!context->in_tkt_ktypes) { + kret = ENOMEM; + goto cleanup; + } + + for (i=0; iin_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 *) calloc(context->tgs_ktype_count+1, + sizeof(krb5_enctype)); + if (!context->tgs_ktypes) { + kret = ENOMEM; + goto cleanup; + } + for (i=0; itgs_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; + + /* 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->dal_handle, + &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) + calloc(1, sizeof(struct _krb5_os_context))) && + (remain >= 4*sizeof(krb5_int32))) { + 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); +#ifndef LEAN_CLIENT + if (!kret) + kret = krb5_register_serializer(kcontext, &krb5_profile_ser_entry); +#endif /* LEAN_CLIENT */ + return(kret); +} diff --git a/krb5-1-7/src/lib/krb5/krb/ser_eblk.c b/krb5-1-7/src/lib/krb5/krb/ser_eblk.c new file mode 100644 index 000000000..8bce41cf1 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_eblk.c @@ -0,0 +1,256 @@ +/* + * lib/krb5/krb/ser_eblk.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *) + calloc(1, 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-7/src/lib/krb5/krb/ser_key.c b/krb5-1-7/src/lib/krb5/krb/ser_key.c new file mode 100644 index 000000000..25522de7b --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/ser_key.c @@ -0,0 +1,198 @@ +/* + * lib/krb5/krb/ser_key.c + * + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 *) calloc(1, 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-7/src/lib/krb5/krb/ser_princ.c b/krb5-1-7/src/lib/krb5/krb/ser_princ.c new file mode 100644 index 000000000..b04638de0 --- /dev/null +++ b/krb5-1-7/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); + free(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; + + free(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-7/src/lib/krb5/krb/serialize.c b/krb5-1-7/src/lib/krb5/krb/serialize.c new file mode 100644 index 000000000..f78bc1618 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/serialize.c @@ -0,0 +1,273 @@ +/* + * 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; iser_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_entry * stable; + + kret = 0; + /* See if it's already there, if so, we're good to go. */ + if (!(stable = (krb5_ser_entry *)krb5_find_serializer(kcontext, + entry->odtype))) { + /* + * Can't find our type. Create a new entry. + */ + if ((stable = (krb5_ser_entry *) 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) free(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)) { + store_32_be(iarg, *bufp); + *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 = load_32_be(*bufp); + *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-7/src/lib/krb5/krb/set_realm.c b/krb5-1-7/src/lib/krb5/krb/set_realm.c new file mode 100644 index 000000000..9a96cd1ca --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/set_realm.c @@ -0,0 +1,51 @@ +/* + * 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 = strdup(realm); + if (!newrealm) + return -ENOMEM; + + (void) free(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-7/src/lib/krb5/krb/srv_dec_tkt.c b/krb5-1-7/src/lib/krb5/krb/srv_dec_tkt.c new file mode 100644 index 000000000..b5cf260f2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/srv_dec_tkt.c @@ -0,0 +1,97 @@ +/* + * lib/krb5/krb/srv_dec_tkt.c + * + * Copyright 2006, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 + +#ifndef LEAN_CLIENT +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; +} +#endif /* LEAN_CLIENT */ + diff --git a/krb5-1-7/src/lib/krb5/krb/srv_rcache.c b/krb5-1-7/src/lib/krb5/krb/srv_rcache.c new file mode 100644 index 000000000..7d6b68a7e --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/srv_rcache.c @@ -0,0 +1,92 @@ +/* + * 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 +#include + +/* 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; + krb5_error_code retval; + unsigned int i; + struct k5buf buf; +#ifdef HAVE_GETEUID + unsigned long uid = geteuid(); +#endif + + if (piece == NULL) + return ENOMEM; + + cachetype = krb5_rc_default_type(context); + + krb5int_buf_init_dynamic(&buf); + krb5int_buf_add(&buf, cachetype); + krb5int_buf_add(&buf, ":"); + for (i = 0; i < piece->length; i++) { + if (piece->data[i] == '-') + krb5int_buf_add(&buf, "--"); + else if (!isvalidrcname((int) piece->data[i])) + krb5int_buf_add_fmt(&buf, "-%03o", piece->data[i]); + else + krb5int_buf_add_len(&buf, &piece->data[i], 1); + } +#ifdef HAVE_GETEUID + krb5int_buf_add_fmt(&buf, "_%lu", uid); +#endif + + cachename = krb5int_buf_data(&buf); + if (cachename == NULL) + return ENOMEM; + + retval = krb5_rc_resolve_full(context, &rcache, cachename); + if (retval) + goto cleanup; + + retval = krb5_rc_recover_or_initialize(context, rcache, + context->clockskew); + if (retval) + goto cleanup; + + *rcptr = rcache; + rcache = 0; + retval = 0; + +cleanup: + if (rcache) + krb5_rc_close(context, rcache); + if (cachename) + free(cachename); + return retval; +} diff --git a/krb5-1-7/src/lib/krb5/krb/str_conv.c b/krb5-1-7/src/lib/krb5/krb/str_conv.c new file mode 100644 index 000000000..2413cebcd --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/str_conv.c @@ -0,0 +1,388 @@ +/* + * lib/kadm/str_conv.c + * + * Copyright 1995, 1999, 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. + * + */ + +/* + * 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 + +/* 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" }, +#if PKINIT_APPLE +{ KRB5_KDB_SALTTYPE_CERTHASH, "certhash", "PKINIT Cert Hash" } +#endif /* PKINIT_APPLE */ +}; +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= buflen) + return(ENOMEM); + return(0); + } + 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 + +#ifndef HAVE_LOCALTIME_R +static inline struct tm * +localtime_r(const time_t *t, struct tm *buf) +{ + struct tm *tm = localtime(t); + if (tm == NULL) + return NULL; + *buf = *tm; + return buf; +} +#endif + +krb5_error_code KRB5_CALLCONV +krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp) +{ + int i; + struct tm timebuf, timebuf2; + 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); + if (localtime_r(&now, &timebuf2) == NULL) + return EINVAL; + for (i=0; i= sftime_default_len) { + snprintf(buffer, buflen, "%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; ideltat 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) + snprintf(buffer, buflen, "%d:%02d:%02d", hours, minutes, seconds); + else if (hours || minutes || seconds) + snprintf(buffer, buflen, "%d %s %02d:%02d:%02d", days, + (days > 1) ? "days" : "day", + hours, minutes, seconds); + else + snprintf(buffer, buflen, "%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-7/src/lib/krb5/krb/strftime.c b/krb5-1-7/src/lib/krb5/krb/strftime.c new file mode 100644 index 000000000..f2a5cb719 --- /dev/null +++ b/krb5-1-7/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 +#include + +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-7/src/lib/krb5/krb/strptime.c b/krb5-1-7/src/lib/krb5/krb/strptime.c new file mode 100644 index 000000000..ac52d5c22 --- /dev/null +++ b/krb5-1-7/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 +#include +#include + +#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-7/src/lib/krb5/krb/t_ad_fx_armor.c b/krb5-1-7/src/lib/krb5/krb/t_ad_fx_armor.c new file mode 100644 index 000000000..74d7e5f1a --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/t_ad_fx_armor.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#define test(x) do {retval = (x); \ + if(retval != 0) { \ + const char *errmsg = krb5_get_error_message(context, retval); \ + fprintf(stderr, "Error message: %s\n", errmsg); \ + abort(); } \ + } while(0); + +krb5_authdata ad_fx_armor = {0, KRB5_AUTHDATA_FX_ARMOR, 1, ""}; +krb5_authdata *array[] = {&ad_fx_armor, NULL}; + + +int main( int argc, char **argv) +{ + krb5_context context; + krb5_ccache ccache = NULL; + krb5_creds creds, *out_creds = NULL; + krb5_error_code retval = 0; + test(krb5_init_context(&context)); + memset(&creds, 0, sizeof(creds)); + creds.authdata = array; + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_get_principal(context, ccache, &creds.client)); + test(krb5_parse_name(context, argv[1], &creds.server)); + test(krb5_get_credentials(context, 0, ccache, &creds, &out_creds)); + test(krb5_cc_destroy(context, ccache)); + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_initialize(context, ccache, out_creds->client)); + test(krb5_cc_store_cred(context, ccache, out_creds)); + test(krb5_cc_close(context,ccache)); + return 0; + +} diff --git a/krb5-1-7/src/lib/krb5/krb/t_authdata.c b/krb5-1-7/src/lib/krb5/krb/t_authdata.c new file mode 100644 index 000000000..8b786875f --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/t_authdata.c @@ -0,0 +1,103 @@ +/* + * lib/krb5/krb/t_authdata.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.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 authorization data search + */ + +#include +#include +#include +#include + +krb5_authdata ad1 = { + KV5M_AUTHDATA, + 22, + 4, + (unsigned char *) "abcd"}; +krb5_authdata ad2 = { + KV5M_AUTHDATA, + 23, + 5, + (unsigned char *) "abcde" +}; + +krb5_authdata ad3= { + KV5M_AUTHDATA, + 22, + 3, + (unsigned char *) "ab" +}; +/* we want three results in the return from krb5int_find_authdata so +it has to grow its list. +*/ +krb5_authdata ad4 = { + KV5M_AUTHDATA, + 22, + 5, + (unsigned char *)"abcd" +}; + +krb5_authdata *adseq1[] = {&ad1, &ad2, &ad4, NULL}; + +krb5_authdata *adseq2[] = {&ad3, NULL}; + +static void compare_authdata(const krb5_authdata *adc1, krb5_authdata *adc2) { + assert(adc1->ad_type == adc2->ad_type); + assert(adc1->length == adc2->length); + assert(memcmp(adc1->contents, adc2->contents, adc1->length) == 0); +} + +int main() +{ + krb5_context context; + krb5_authdata **results; + krb5_authdata *container[2]; + krb5_authdata **container_out; + + + assert(krb5_init_context(&context) == 0); + assert(krb5_merge_authdata(context, adseq1, adseq2, &results) == 0); + compare_authdata(results[0], &ad1); + compare_authdata( results[1], &ad2); + compare_authdata(results[2], &ad4); + compare_authdata( results[3], &ad3); + assert(results[4] == NULL); + krb5_free_authdata(context, results); + container[0] = &ad3; + container[1] = NULL; + assert(krb5_encode_authdata_container( context, KRB5_AUTHDATA_IF_RELEVANT, container, &container_out) == 0); + assert(krb5int_find_authdata(context, + adseq1, container_out, 22, &results) == 0); + compare_authdata(&ad1, results[0]); + compare_authdata( results[1], &ad4); + compare_authdata( results[2], &ad3); + assert( results[3] == NULL); + krb5_free_authdata(context, results); + krb5_free_authdata(context, container_out); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1-7/src/lib/krb5/krb/t_deltat.c b/krb5-1-7/src/lib/krb5/krb/t_deltat.c new file mode 100644 index 000000000..a07ba4232 --- /dev/null +++ b/krb5-1-7/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-7/src/lib/krb5/krb/t_expand.c b/krb5-1-7/src/lib/krb5/krb/t_expand.c new file mode 100644 index 000000000..a8b2757df --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/t_expand.c @@ -0,0 +1,2 @@ +#define TEST +#include "chk_trans.c" diff --git a/krb5-1-7/src/lib/krb5/krb/t_kerb.c b/krb5-1-7/src/lib/krb5/krb/t_kerb.c new file mode 100644 index 000000000..8627922b2 --- /dev/null +++ b/krb5-1-7/src/lib/krb5/krb/t_kerb.c @@ -0,0 +1,227 @@ +/* + * This driver routine is used to test many of the standard Kerberos library + * routines. + */ + +#include "krb5.h" +#include "autoconf.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +#define ANAME_SZ 40 +#define INST_SZ 40 +#define REALM_SZ 40 + 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 \n", progname); + fprintf(stderr, "\t%s parse_name \n", progname); + fprintf(stderr, "\t%s set_realm \n", progname); + fprintf(stderr, "\t%s string_to_timestamp